【发布时间】:2013-08-02 20:36:06
【问题描述】:
扩展的Application 类可以声明全局变量。还有其他原因吗?
【问题讨论】:
-
这只是我脑海中的一个想法,但您应该能够覆盖 onCreate 并显示一次性启动屏幕而不是 MainActivity,即第一次启动时的介绍屏幕用户打开应用程序。
标签: android android-application-class
扩展的Application 类可以声明全局变量。还有其他原因吗?
【问题讨论】:
标签: android android-application-class
有时您想要存储数据,例如需要从多个活动中访问的全局变量 - 有时在应用程序中的任何地方。在这种情况下,Application 对象将为您提供帮助。
例如,如果要获取每个http请求的基本认证数据,可以在应用对象中实现认证数据的方法。
在此之后,您可以在任何这样的活动中获取用户名和密码:
MyApplication mApplication = (MyApplication)getApplicationContext();
String username = mApplication.getUsername();
String password = mApplication.getPassword();
最后,请记住将 Application 对象用作单例对象:
public class MyApplication extends Application {
private static MyApplication singleton;
public MyApplication getInstance(){
return singleton;
}
@Override
public void onCreate() {
super.onCreate();
singleton = this;
}
}
更多信息请点击Application Class
【讨论】:
来源:https://github.com/codepath/android_guides/wiki/Understanding-the-Android-Application-Class
在许多应用程序中,无需直接使用应用程序类。但是,自定义应用程序类有一些可接受的用途:
- 在创建您的第一个活动之前需要运行的特殊任务
- 需要在所有组件之间共享的全局初始化(崩溃报告、持久性)
- 用于轻松访问静态不可变数据(例如共享网络客户端对象)的静态方法
您永远不应该在 Application 对象中存储可变的实例数据,因为如果您假设您的数据将保留在那里,您的应用程序将不可避免地在某个时候崩溃并出现 NullPointerException。应用程序对象不能保证永远留在内存中,它会被杀死。与流行的看法相反,该应用程序不会从头开始重新启动。 Android 将创建一个新的 Application 对象并在用户之前所在的位置启动 Activity,从而给人一种应用程序从一开始就没有被杀死的错觉。
【讨论】:
添加到其他答案中,声明您可能希望在应用程序范围内存储变量,对于需要绑定到您的应用程序的任何长时间运行的线程或其他对象,您不使用活动(应用程序不是活动).. 比如不能请求绑定的服务.. 那么绑定到应用实例是首选。这种方法唯一明显的警告是,只要应用程序处于活动状态,对象就会一直存在,因此需要对内存进行更多的隐式控制,否则您将遇到与内存相关的问题,例如泄漏。
您可能会发现有用的其他一点是,按照操作顺序,应用程序在任何活动之前首先启动。在此时间范围内,如果您愿意,您可以在第一次活动之前准备任何必要的内务处理。
2018-10-19 11:31:55.246 8643-8643/: application created
2018-10-19 11:31:55.630 8643-8643/: activity created
【讨论】:
apk 文件,它由
多个有用的块,例如Activitys、Services 和
其他人。Application 中的状态,无论
用户正在使用的Activity,Application,Cursor 并再次关闭它
再次表现不佳,Intents 来传递数据,但它很笨拙而且很活跃
根据内存可用性,它本身可能在特定情况下不存在。Application 访问变量,Application 启动某些操作,例如分析
等等,因为应用程序类在Activitys 或之前启动
Servicess 正在运行中,【讨论】:
我看到这个问题缺少答案。我扩展 Application 因为我使用 Bill Pugh Singleton 实现 (see reference) 并且我的一些单身人士需要上下文。 Application 类如下所示:
public class MyApplication extends Application {
private static final String TAG = MyApplication.class.getSimpleName();
private static MyApplication sInstance;
@Contract(pure = true)
@Nullable
public static Context getAppContext() {
return sInstance;
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate() called");
sInstance = this;
}
}
单例看起来像这样:
public class DataManager {
private static final String TAG = DataManager.class.getSimpleName();
@Contract(pure = true)
public static DataManager getInstance() {
return InstanceHolder.INSTANCE;
}
private DataManager() {
doStuffRequiringContext(MyApplication.getAppContext());
}
private static final class InstanceHolder {
@SuppressLint("StaticFieldLeak")
private static final DataManager INSTANCE = new DataManager();
}
}
这样我就不需要每次使用单例时都有上下文,并且可以用最少的代码进行延迟同步初始化。
提示:更新 Android Studio 单例模板可以节省大量时间。
【讨论】:
我认为您可以将 Application 类用于许多事情,但它们都与您在启动任何活动或服务之前需要做一些事情有关。 例如,在我的应用程序中,我使用自定义字体。而不是调用
Typeface.createFromAsset()
从每个 Activity 从 Assets 文件夹中获取我的字体的引用(这很糟糕,因为它会导致内存泄漏,因为您每次调用该方法时都保留对资产的引用),我从 @987654322 执行此操作我的应用程序类中的@方法:
private App appInstance;
Typeface quickSandRegular;
...
public void onCreate() {
super.onCreate();
appInstance = this;
quicksandRegular = Typeface.createFromAsset(getApplicationContext().getAssets(),
"fonts/Quicksand-Regular.otf");
...
}
现在,我也有这样定义的方法:
public static App getAppInstance() {
return appInstance;
}
还有这个:
public Typeface getQuickSandRegular() {
return quicksandRegular;
}
所以,在我的应用程序的任何地方,我所要做的就是:
App.getAppInstance().getQuickSandRegular()
对我来说,Application 类的另一个用途是在需要连接的活动和服务实际启动并采取必要措施之前检查设备是否已连接到 Internet。
【讨论】:
应用类的最佳使用。 示例:假设您需要在启动完成时重新启动警报管理器。
public class BaseJuiceApplication extends Application implements BootListener {
public static BaseJuiceApplication instance = null;
public static Context getInstance() {
if (null == instance) {
instance = new BaseJuiceApplication();
}
return instance;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onBootCompleted(Context context, Intent intent) {
new PushService().scheduleService(getInstance());
//startToNotify(context);
}
【讨论】:
不是答案,而是观察:请记住,扩展应用程序对象中的数据不应与活动实例相关联,因为您可能有两个同时运行的同一活动的实例(一个在前台,一个不可见)。
例如,您通过启动器正常启动活动,然后“最小化”它。然后,您启动另一个应用程序(即 Tasker),它启动您的另一个活动实例,例如为了创建快捷方式,因为您的应用程序支持 android.intent.action.CREATE_SHORTCUT。如果随后创建了快捷方式,并且这个创建快捷方式的 Activity 调用修改了应用程序对象的数据,那么在后台运行的 Activity 将开始使用这个修改后的应用程序对象,一旦它被带回前台。
【讨论】:
使用扩展应用程序只是让您的应用程序确保在您的应用程序运行期间执行您想要的任何类型的操作。现在它可能是任何类型的变量,假设如果你想从服务器获取一些数据,那么你可以将你的 asynctask 放在应用程序中,这样它就会每次连续获取,这样你就可以自动获得更新的数据。使用这个链接更多知识......
http://www.intridea.com/blog/2011/5/24/how-to-use-application-object-of-android
【讨论】:
您可以在不创建对象的情况下访问任何类的变量,如果它由应用程序扩展。它们可以被全局调用,并且它们的状态一直保持到应用程序没有被杀死。
【讨论】:
顺便说一句,我想不出一个真实的场景,其中扩展 Application 比另一种方法更可取,或者是完成某事所必需的。如果您有一个昂贵且经常使用的对象,您可以在检测到该对象当前不存在时在 IntentService 中对其进行初始化。应用程序本身运行在 UI 线程上,而 IntentService 运行在自己的线程上。
我更喜欢使用显式 Intent 将数据从 Activity 传递到 Activity,或者使用 SharedPreferences。还有一些方法可以使用接口将数据从 Fragment 传递到其父 Activity。
【讨论】:
"prefer to pass data from Activity to Activity with explicit Intents, or use SharedPreferences"。我们应该始终尽可能地消除全局状态,并使用标准的 Android 工具进行全局状态管理,而不是静态变量/单例等。
应用程序类是具有应用程序完整生命周期的对象。它是您作为应用程序的最高层。可能的用法示例:
您可以在应用程序启动时添加您需要的内容,方法是在 Application 类中重写 onCreate。
存储从 Activity 跳转到 Activity 的全局变量。像 Asynctask。
等
【讨论】:
Application 类是一个单例,您可以从任何 Activity 或任何其他拥有 Context 对象的地方访问它。
您还可以获得一点生命周期。
您可以使用应用程序的 onCreate 方法来实例化昂贵但经常使用的对象,例如分析助手。然后,您可以在任何地方访问和使用这些对象。
【讨论】: