没有活动的Android Context?和其他无活动编程?
Posted
技术标签:
【中文标题】没有活动的Android Context?和其他无活动编程?【英文标题】:Android Context without being in an activity? And other activity-less programming? 【发布时间】:2013-06-30 17:56:52 【问题描述】:我会努力把它变成一个综合性的问题:
我正在编写一个方法来获取包含 android 设备城市名称的字符串,该名称由 LocationManager
和 getLastKnownLocation()
以及所有这些确定。
然后我意识到我需要在另一个活动中再次做同样的事情,所以为什么不创建一个完全独立的类 (LocationFinder
) 可以在我的程序中使用,而不是到处编写重复的代码?
但我遇到了让我困惑的问题。例如,如果我创建这个类 (LocationFinder
),它是否应该扩展 Activity,即使它从未真正可视化?这个类所要做的就是拥有各种 getter,如 getLastKnownCity()
或 getCurrentCity()
并返回字符串。我认为它不必扩展 Activity 类,因为它实际上不是一个活动。
然后我用什么上下文:
Geocoder geocoder = new Geocoder(Context context, Locale locale)
?
这让我认为它必须是一项活动。于是我扩展了Activity,并将构造函数替换为
@Override
protected void onCreate(..............
但由于某种原因,它永远不会被调用,即使我放了
String city = new LocationFinder().getLastKnownCity();
我LocationFinder
的onCreate()
的第一行是
System.out.println("HEY!")
它甚至从来没有达到过。我在android.internal.os.LoggingPrintStream.println()
和其他地方得到一个空指针。
另外,还有很多来自 Activity 类的系统常量。例如,我需要访问LOCATION_SERVICE
,这是一个字符串,如果不扩展 Activity,我将无法获得它。当然,我可以作弊并只输入文字字符串,但这感觉不对。
【问题讨论】:
【参考方案1】:编辑:如果可能,请使用 frogmanx 的答案。这应该只在他的答案不可能使用时使用。 (即,需要立即获得上下文的单身人士。)
听起来您应该扩展 Application 而不是 Activity。
使您的应用程序如下所示:
public class MyApplication extends Application
private static MyApplication instance;
public MyApplication()
instance = this;
public static MyApplication getInstance()
return instance;
然后将此属性添加到清单的应用程序标签中:
<application android:name=".your.package.MyApplication" ... />
毕竟,您可以通过从任何地方调用MyApplication.getInstance()
来获取上下文。
【讨论】:
不完全是我的问题,但你的回答帮助了我!谢谢 真棒 +1 正是我的情况,需要上下文的单身人士。我花了很长时间才找到这个! 这给了我 java.lang.IllegalAccessException【参考方案2】:在构造你的类时,你可以有一个构造函数,它接受一个 Context 并在你的类中为其分配一个本地 Context 对象。
public class LocationFinder
private Context myContext;
private Geocoder geocoder;
public LocationFinder(Context context)
myContext = context;
geocoder = new Geocoder(myContext);
然后,当您尝试访问此类时,请确保将其初始化为:
public class TestActivity extends Activity
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LocationFinder lFinder = new LocationFinder(getApplication());
当然,您不能从将要运行的每个类访问上下文。因此,对 View 的引用就足够了。
LocationFinder lFinder = new LocationFinder(anyView.getApplication());
【讨论】:
谢谢!只是想知道,像您推荐的那样,使用 getApplicationContext() 而不是传入 Activity 的上下文会很糟糕吗?我仍然缺乏对上下文的理解,即使我一遍又一遍地阅读它们的定义......我只是看不出是什么让一个 Activity 的上下文与另一个不同。 没错,当Activity的onDestroy被调用时,对上下文的引用就会被销毁。【参考方案3】:should it extend Activity, even though it is never actually visualized?
没有。来自安卓docs
活动是用户可以做的单一的、专注的事情。几乎 所有活动都与用户交互,因此 Activity 类采用 为您创建一个窗口,您可以在其中放置您的 UI 设置内容视图(视图)
将 Activity 视为用户看到的屏幕。
然后我用什么上下文 Geocoder geocoder = new Geocoder(Context context, Locale locale)
Activity
类扩展了 Context
,许多其他类也是如此,包括 Application
。 上下文提供对与扩展上下文的类关联的资源的访问。
当需要与与该 Activity 关联的资源和由具体 Activity 类实现的方法进行交互时,您只需要并且应该只使用 Activity 上下文。当您确实需要访问该上下文时,您会将其传递给需要访问的类,通常作为该类的构造函数的参数。
如果您确实在扩展它的 Activity 之外传递了 Activity 上下文,请确保引用的范围和生命周期小于或等于扩展 Activity,否则如果 Activity 被销毁,您将泄漏大量内存因为垃圾收集器无法释放内存,因为存在对上下文的引用。
如果您查看 Geocoder 的构造函数,您会发现它采用 Context 作为参数,如您所知。关于为什么在描述中需要上下文有一个线索:
Geocoder(Context context, Locale locale)
Constructs a Geocoder whose responses will be localized for the given Locale. [1]:
需要上下文的原因是为了获取有关平台区域设置和当前系统区域设置的系统信息。
因此,在您的示例中,您可以简单地将 Application 上下文传递给构造函数,您可以使用 getApplicationContext()
获取对其的引用
例如,我需要获取 LOCATION_SERVICE,它是一个字符串,如果不扩展 Activity 就无法获取该字符串
您可以从应用程序上下文中获取它。
【讨论】:
谢谢!只是想知道,在地理编码器(上下文上下文...)中使用 getApplicationContext() 作为我的上下文是不明智的吗?其他人建议从实例化这个新类的活动中传递上下文,我不确定哪个是最好的方法。再次感谢。 关键是,您是否需要从Geocoder
访问您的Activity
?好的设计说不。如果您需要将值传递给您的Activity
,请使用侦听器。您始终可以定义自己的 Interface
来执行自定义回调,例如更新TextView
。使用应用程序上下文没有什么“坏事”。它保证是一个单例并且在应用程序生命周期中始终存在,所以最好把这个问题问成“我为什么需要一个 Activity 上下文”?以上是关于没有活动的Android Context?和其他无活动编程?的主要内容,如果未能解决你的问题,请参考以下文章
Android学习之基础知识十六 — Android开发高级技巧的掌握
Android 全局获取 Context 与使用 Intent 传递对象