扩展Application
类可以声明全局变量。还有其他原因吗?
13 回答
介绍:
- 如果我们考虑
apk
移动设备中的文件,它由多个有用的块组成,例如Activity
s、Service
s 等。 - 这些组件不会定期相互通信,并且不要忘记它们有自己的生命周期。这表明它们可能在某个时间处于活动状态,而在另一时间处于不活动状态。
要求:
- 有时我们可能需要一个场景,我们需要访问一个变量及其整个状态,
Application
而不管Activity
用户使用的是什么, - 一个例子是,用户可能需要访问一个变量,该变量包含他的人员信息(例如姓名),该信息必须通过
Application
, Cursor
我们可以使用 SQLite,但是一次又一次地创建和关闭它对性能不好,- 我们可以使用
Intent
s 来传递数据,但它很笨拙,并且在特定情况下可能不存在活动本身,具体取决于内存可用性。
应用类的用途:
- 跨域访问变量
Application
, - 您可以使用
Application
来启动某些事情,例如分析等,因为应用程序类是在Activity
s 或Services
s 运行之前启动的, - 有一个称为 onConfigurationChanged() 的重写方法,当应用程序配置更改时触发(水平到垂直,反之亦然),
- 还有一个称为 onLowMemory() 的事件,当 Android 设备内存不足时触发。
应用程序类是具有应用程序完整生命周期的对象。它是您作为应用程序的最高层。示例可能的用法:
您可以通过覆盖 Application 类中的 onCreate 来添加应用程序启动时所需的内容。
存储从 Activity 跳转到 Activity 的全局变量。就像异步任务一样。
ETC
有时你想存储数据,比如需要从多个活动中访问的全局变量——有时在应用程序中的任何地方。在这种情况下,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 比另一种方法更可取,或者是完成某些事情所必需的。如果您有一个昂贵且经常使用的对象,您可以在检测到该对象当前不存在时在 IntentService 中对其进行初始化。应用程序本身运行在 UI 线程上,而 IntentService 运行在自己的线程上。
我更喜欢使用显式 Intent 将数据从 Activity 传递到 Activity,或者使用 SharedPreferences。还有一些方法可以使用接口将数据从 Fragment 传递到其父 Activity。
Application 类是一个单例,您可以从任何活动或任何其他拥有 Context 对象的地方访问它。
您还可以获得一点生命周期。
您可以使用应用程序的 onCreate 方法来实例化昂贵但经常使用的对象,例如分析助手。然后,您可以在任何地方访问和使用这些对象。
应用类的最佳使用。示例:假设您需要在启动完成时重新启动警报管理器。
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。如果随后创建了快捷方式,并且该活动的创建快捷方式的调用修改了应用程序对象的数据,那么在后台运行的活动将开始使用这个修改后的应用程序对象,一旦它被带回前台。
我看到这个问题缺少答案。我扩展Application
是因为我使用 Bill Pugh Singleton实现(请参阅参考资料)并且我的一些单例需要上下文。该类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 文件夹中获取我的字体的引用(这很糟糕,因为它会导致内存泄漏,因为您每次调用该方法时都保留对资产的引用),我从onCreate()
Application 类中的方法执行此操作:
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。
来源: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
如果它由 Application 扩展,您可以在不创建对象的情况下访问任何类的变量。它们可以被全局调用并且它们的状态被保持直到应用程序没有被杀死。
扩展应用程序的使用只是使您的应用程序确保在整个应用程序运行期间您想要的任何类型的操作。现在它可能是任何类型的变量,假设如果你想从服务器获取一些数据,那么你可以将你的 asynctask 放在应用程序中,这样它就会每次连续获取,这样你就可以自动获得更新的数据。使用这个链接为了更多的知识......
http://www.intridea.com/blog/2011/5/24/how-to-use-application-object-of-android