16

我会非常努力地把它变成一个综合性的问题:

我正在编写一个方法来获取一个包含 Android 设备城市名称的字符串,该名称由LocationManagerandgetLastKnownLocation()和所有这些决定。

然后我意识到我需要在另一个活动中再次做同样的事情,那么为什么不创建一个完全独立的类 ( LocationFinder),我可以在我的程序中使用它,而不是到处编写重复的代码呢?

但是我遇到了让我困惑的问题。例如,如果我创建这个类 ( LocationFinder),它是否应该扩展 Activity,即使它从未真正可视化?这个类所要做的就是拥有各种 getter,比如getLastKnownCity()orgetCurrentCity()和返回字符串。我认为它不必扩展 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 类的系统常量。例如,我需要获取 at LOCATION_SERVICE,这是一个字符串,如果不扩展 Activity 就无法获取。当然,我可以作弊并只输入文字字符串,但这感觉不对。

4

3 回答 3

25

编辑:如果可能,请使用 frogmanx 的答案。这应该只在他的答案不可能使用时使用。(即,需要立即获得上下文的单身人士。)

听起来你应该扩展应用程序而不是活动。

使您的应用程序如下所示:

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()从任何地方调用来获取上下文。

于 2013-07-03T06:43:40.677 回答
14

在构造类时,您可以有一个构造函数,它接受一个 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());
于 2013-07-03T06:57:57.400 回答
5
should it extend Activity, even though it is never actually visualized?

不,来自 Android文档

活动是用户可以做的一个单一的、有重点的事情。几乎所有活动都与用户交互,因此 Activity 类负责为您创建一个窗口,您可以在其中放置带有 setContentView(View) 的 UI

将 Activity 视为用户看到的屏幕。

但是然后我为 Geocoder 使用什么上下文 geocoder = new Geocoder(Context context, Locale locale)

该类Activity扩展Context,许多其他类包括Application. 上下文提供对与扩展上下文的类关联的资源的访问。

当需要与与该 Activity 关联的资源和由具体 Activity 类实现的方法进行交互时,您只需要并且应该只使用 Activity 上下文。当您确实需要访问该上下文时,您会将其传递给需要访问的类,通常作为该类的构造函数的参数。

如果您确实在扩展它的活动之外传递了活动上下文,请确保引用的范围和生命周期小于或等于扩展活动,否则如果活动因垃圾而被破坏,您将泄漏大量内存收集器无法释放内存,因为存在对上下文的引用。

如果您查看 Geocoder 的构造函数,您会发现它采用 Context 作为参数,如您所知。关于为什么在描述中需要上下文有一个线索:

     Geocoder(Context context, Locale locale)
Constructs a Geocoder whose responses will be localized for the given Locale.  [1]: 

需要 Context 的原因是为了访问有关平台区域设置和当前系统区域设置的系统信息。

因此,在您的示例中,您可以简单地将 Application 上下文传递给构造函数,您可以使用getApplicationContext()

例如,我需要到达 LOCATION_SERVICE,它是一个字符串,如果不扩展 Activity 就无法获得

您可以从应用程序上下文中获取它。

于 2013-07-03T07:11:51.400 回答