Using Application context everywhere?
在Android应用中,以下方法有什么问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 | public class MyApp extends android.app.Application { private static MyApp instance; public MyApp() { instance = this; } public static Context getContext() { return instance; } } |
并将其传递到任何地方(例如SQLiteOpenHelper),其中需要上下文(当然不泄漏)?
这种方法存在一些潜在的问题,但在很多情况下(例如你的例子)它会很好用。
特别是在处理需要
此外,作为模式的替代方法,您可以使用在
根据我的经验,这种方法不应该是必要的。如果您需要任何上下文,通常可以通过调用View.getContext()并使用在此获得的
总的来说,对于这种情况,您的方法似乎没有问题,但在处理
有人问过:单例如何返回空指针?
我正在回答这个问题。 (我无法在评论中回答,因为我需要发布代码。)
它可能在两个事件之间返回null:(1)加载类,(2)创建此类的对象。这是一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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); } } |
我们运行代码:
1 2 3 4 | $ javac A.java $ java A x:X@a63599 y:Y@9036e x:null y:null |
第二行显示Y.xinstance和X.yinstance为空;它们为null,因为变量X.xinstance和Y.yinstance在它们为null时被读取。
这可以修复吗?是,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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:"+X.y); } } |
并且此代码没有显示任何异常:
1 2 3 4 | $ javac A.java $ java A x:X@1c059f6 y:Y@152506e x:X@1c059f6 y:Y@152506e |
但这不是Android
再一次:第一个示例和第二个示例之间的区别在于,如果静态指针为null,则第二个示例创建一个实例。但是程序员在系统决定执行之前无法创建Android应用程序对象。
UPDATE
另一个令人费解的例子,其中初始化的静态字段碰巧是
Main.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | enum MyEnum { FIRST,SECOND; private static String prefix="<", suffix=">"; String myName; MyEnum() { myName = makeMyName(); } String makeMyName() { return prefix + name() + suffix; } String getMyName() { return myName; } } public class Main { public static void main(String args[]) { System.out.println("first:"+MyEnum.FIRST+" second:"+MyEnum.SECOND); System.out.println("first:"+MyEnum.FIRST.makeMyName()+" second:"+MyEnum.SECOND.makeMyName()); System.out.println("first:"+MyEnum.FIRST.getMyName()+" second:"+MyEnum.SECOND.getMyName()); } } |
你得到:
1 2 3 4 5 | $ javac Main.java $ java Main first: FIRST second: SECOND first: <FIRST> second: <SECOND> first: nullFIRSTnull second: nullSECONDnull |
注意,你不能将静态变量声明移到一行上面,代码不会编译。
申请类别:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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中声明应用程序:
1 2 3 | <application android:name=".MyApplication" ... /> |
用法:
1 | MyApplication.getAppContext() |
您正在尝试创建一个包装器来获取应用程序上下文,并且它可能会返回"
根据我的理解,我猜它更好的方法来调用2中的任何一个
这是一个很好的方法。我自己也用它。我只建议覆盖
既然你提到了
我个人认为文档说错了通常不需要子类Application。我认为情况恰恰相反:你应该总是将Application子类化。
我将使用Application Context在构造函数中获取系统服务。这简化了测试和从构图中获益
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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 } |
然后,测试类将使用重载的构造函数。
Android会使用默认构造函数。
我使用相同的方法,我建议更好地编写单例:
1 2 3 4 5 6 7 8 9 10 11 12 | public static MyApp getInstance() { if (instance == null) { synchronized (MyApp.class) { if (instance == null) { instance = new MyApp (); } } } return instance; } |
但是我没有到处使用,我使用
我喜欢它,但我会建议一个单身人士:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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; } } |