到处使用Application上下文?
在Android应用程序中,以下方法有什么不妥之处:
public class MyApp extends android.app.Application { private static MyApp instance; public MyApp() { instance = this; } public static Context getContext() { return instance; } }
并将其传递到需要上下文的地方(例如SQLiteOpenHelper)(当然不会泄漏)?
这种方法存在一些潜在的问题,尽pipe在很多情况下(比如你的例子),它会运行良好。
特别是在处理需要Context
的GUI
,应该小心。 例如,如果将应用程序上下文传递给LayoutInflater
,则会得到一个Exception。 一般而言,您的方法非常好:在Activity's
使用Activity's
Context
以及在上下文之外传递上下文以避免内存泄漏是一个很好的做法。
此外,作为模式的替代方法 ,您可以使用在Context
对象(如Activity)上调用getApplicationContext()
的快捷方式来获取应用程序上下文。
根据我的经验,这种方法不是必须的。 如果你需要任何东西的上下文,通常可以通过调用View.getContext()来获得它,然后使用获得的上下文来调用Context.getApplicationContext()来获得应用程序上下文。 如果您正在尝试从Activity获取Appication上下文,那么您始终可以调用Activity.getApplication() ,它应该能够作为调用SQLiteOpenHelper()所需的上下文来传递。
总的来说,对于这种情况,您的方法似乎没有问题,但是在处理Context时,请确保您不会像Google官方Android开发人员博客
有人问: 单身人士如何返回一个空指针? 我正在回答这个问题。 (我不能在评论中回答,因为我需要发布代码。)
它可能在两个事件之间返回null:(1)类被加载,(2)这个类的对象被创build。 这是一个例子:
class X { static X xinstance; static Y yinstance = Y.yinstance; X() {xinstance=this;} } class Y { static X xinstance = X.xinstance; static Y yinstance; Y() {yinstance=this;} } public class A { public static void main(String[] p) { X x = new X(); Y y = new Y(); System.out.println("x:"+X.xinstance+" y:"+Y.yinstance); System.out.println("x:"+Y.xinstance+" y:"+X.yinstance); } }
让我们运行代码:
$ javac A.java $ java A x:X@a63599 y:Y@9036e x:null y:null
第二行显示Y.xinstance和X.yinstance为空 ; 它们为空,因为variablesX.xinstance和Y.yinstance在空值时被读取。
这可以解决吗? 是,
class X { static Y y = Y.getInstance(); static X theinstance; static X getInstance() {if(theinstance==null) {theinstance = new X();} return theinstance;} } class Y { static X x = X.getInstance(); static Y theinstance; static Y getInstance() {if(theinstance==null) {theinstance = new Y();} return theinstance;} } public class A { public static void main(String[] p) { System.out.println("x:"+X.getInstance()+" y:"+Y.getInstance()); System.out.println("x:"+Y.x+" y:"+Xy); } }
而这段代码显示没有exception:
$ javac A.java $ java A x:X@1c059f6 y:Y@152506e x:X@1c059f6 y:Y@152506e
但是这不是Android Application
对象的选项:程序员不控制创build时间。
再次说明:第一个例子和第二个例子的不同在于,如果静态指针为空,则第二个示例创build一个实例。 但是程序员不能在系统决定去做之前创buildAndroid应用程序对象。
你正试图创build一个包装来获得应用程序上下文,并有可能返回“ null
”指针。
根据我的理解,我猜想更好的方法来调用任何的2 Context.getApplicationContext()
或Activity.getApplication()
。
应用类别:
import android.app.Application; import android.content.Context; public class MyApplication extends Application { private static Context mContext; public void onCreate() { super.onCreate(); mContext = getApplicationContext(); } public static Context getAppContext() { return mContext; } }
在AndroidManifest中声明应用程序:
<application android:name=".MyApplication" ... />
用法:
MyApplication.getAppContext()
这是一个好方法。 我自己也使用它。 我只会build议重写onCreate
来设置单例,而不是使用构造函数。
而且因为你提到了SQLiteOpenHelper
:在onCreate ()
你也可以打开数据库。
就我个人而言,我认为文档中有错误的地方说, 通常不需要子类化应用程序 。 我认为情况正好相反:你总是应用子类。
我将使用应用程序上下文在构造函数中获取系统服务。 这简化了testing和组合的好处
public class MyActivity extends Activity { private final NotificationManager notificationManager; public MyActivity() { this(MyApp.getContext().getSystemService(NOTIFICATION_SERVICE)); } public MyActivity(NotificationManager notificationManager) { this.notificationManager = notificationManager; } // onCreate etc }
然后testing类将使用重载的构造函数。
Android会使用默认的构造函数。
我喜欢它,但我会build议一个单身人士:
package com.mobidrone; import android.app.Application; import android.content.Context; public class ApplicationContext extends Application { private static ApplicationContext instance = null; private ApplicationContext() { instance = this; } public static Context getInstance() { if (null == instance) { instance = new ApplicationContext(); } return instance; } }
我使用相同的方法,我build议单独写一点:
public static MyApp getInstance() { if (instance == null) { synchronized (MyApp.class) { if (instance == null) { instance = new MyApp (); } } } return instance; }
但我没有到处使用,我使用getContext()
和getApplicationContext()
,我可以做到这一点!