在不同的Android代码中,我看到:

 public class MyActivity extends Activity {
    public void method() {
       mContext = this;    // since Activity extends Context
       mContext = getApplicationContext();
       mContext = getBaseContext();
    }
 }

然而,我找不到任何像样的解释,说明哪种方法更可取,以及在什么情况下应该使用哪种方法。

如果您选择了错误的选项,将非常感谢您提供有关该选项的文档指针,以及关于可能出现故障的指导。


当前回答

简单地说

getApplicationContext()正如方法名称所暗示的那样,将使你的应用程序意识到你可以从应用程序的任何地方访问的应用程序范围的细节。所以你可以在服务绑定,广播注册等中使用它。应用程序上下文将一直存在,直到应用程序退出。

getActivity()或这将使你的应用程序意识到当前屏幕,这也是可见的应用程序上下文提供的应用程序级别的细节。你想知道的关于当前屏幕的任何东西比如Window ActionBar Fragementmanger都可以通过这个context得到。基本上和活动扩展上下文。在当前组件(活动)激活之前,该上下文都是激活的

其他回答

造成这种困惑的原因是有很多方法 access上下文,(表面上)没有明显的区别。 下面是四种最常见的方法 活动中的上下文。

getContext()
getBaseContext()
getApplicationContext()
getActionBar().getThemedContext() //new

什么是上下文? 我个人喜欢把上下文看作应用程序在任何给定时间的状态。应用程序上下文表示应用程序的全局或基本配置,活动或服务可以构建在它之上,并表示应用程序的配置实例或它的传递状态。

看看android。content的源代码。Context,你可以看到Context是一个抽象类,类上的注释如下:

Interface to global information about an application environment. This is an abstract class whose implementation is provided by the Android system. It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc. What I take away from this is that Context provides a common implementation to access application level as well as system level resources. Application level resources may be accessing things like String resources [getResources()] or assets [getAssets()] and system-level resource is anything that you access with Context.getSystemService().

事实上,看看这些方法的评论,它们似乎强化了这个概念:

getSystemService(): Return the handle to a system-level service by name. The class of the returned object varies by the requested name. getResources(): Return a Resources instance for your application’s package. getAssets(): Return a Resources instance for your application’s package. It may be worth pointing out that in the Context abstract class, all of the above methods are abstract! Only one instance of getSystemService(Class) has an implementation and that invokes an abstract method. This means, the implementation for these should be provided mostly by the implementing classes, which include:

ContextWrapper
Application
Activity
Service
IntentService

查看API文档,类的层次结构是这样的:

上下文

| - ContextWrapper

| - -应用

|— — 上下文主题包装器

| - - -活动

| - -服务

|— — 意图服务

Since we know that Context itself is not providing any insight, we move down the tree and take a look at the ContextWrapper and realize that there isn't much there either. Since Application extends ContextWrapper, there isn't much to look at over there either since it doesn't override the implementation provided by ContextWrapper. This means that the implementation for Context is provided by the OS and is hidden from the API. You can take a look at the concrete implementation for Context by looking at the source for the ContextImpl class.

我只使用这个和getBaseContext从一个onClick toast(非常绿色的新手到Java和android)。当我的点击器直接在活动中,并且必须在匿名的内部点击器中使用getBaseContext时,我使用这个。我猜这就是getBaseContext的诀窍,它可能返回隐藏内部类的活动的上下文。

首先,我同意我们应该尽可能使用appcontext。然后是"this" in activity。我从来不需要基本的上下文。

在我的测试中,大多数情况下它们是可以互换的。在大多数情况下,您想要获得上下文的原因是访问文件、首选项、数据库等。这些数据最终会以文件的形式反映在应用程序的私有数据文件夹(/data/data/)中。无论你使用哪个上下文,它们都将被映射到相同的文件夹/文件,所以没问题。

这就是我观察到的。也许在某些情况下你应该区分它们。

以下是我在使用语境方面的发现:

1) . 在一个活动本身中,使用它来膨胀布局和菜单,注册上下文菜单,实例化小部件,启动其他活动,在一个活动中创建新的Intent,实例化首选项,或在一个活动中可用的其他方法。

膨胀布局:

View mView = this.getLayoutInflater().inflate(R.layout.myLayout, myViewGroup);

增加菜单:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    this.getMenuInflater().inflate(R.menu.mymenu, menu);
    return true;
}

注册上下文菜单:

this.registerForContextMenu(myView);

实例化部件:

TextView myTextView = (TextView) this.findViewById(R.id.myTextView);

启动一个活动:

Intent mIntent = new Intent(this, MyActivity.class);
this.startActivity(mIntent);

实例化偏好:

SharedPreferences mSharedPreferences = this.getPreferenceManager().getSharedPreferences();

2) . 对于应用程序范围的类,使用getApplicationContext(),因为该上下文在应用程序的生命周期内存在。

检索当前Android包的名称:

public class MyApplication extends Application {    
    public static String getPackageName() {
        String packageName = null;
        try {
            PackageInfo mPackageInfo = getApplicationContext().getPackageManager().getPackageInfo(getApplicationContext().getPackageName(), 0);
            packageName = mPackageInfo.packageName;
        } catch (NameNotFoundException e) {
            // Log error here.
        }
        return packageName;
    }
}

绑定一个应用范围的类:

Intent mIntent = new Intent(this, MyPersistent.class);
MyServiceConnection mServiceConnection = new MyServiceConnection();
if (mServiceConnection != null) {
    getApplicationContext().bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
}

3)。对于监听器和其他类型的Android类(例如contenttobserver),使用上下文替换如下:

mContext = this;    // Example 1
mContext = context; // Example 2

其中this或context是类(Activity等)的上下文。

活动上下文替换:

public class MyActivity extends Activity {
    private Context mContext;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);        
        mContext = this;
    }
}

侦听器上下文替换:

public class MyLocationListener implements LocationListener {
    private Context mContext;
    public MyLocationListener(Context context) {
        mContext = context;
    }
}

contenttobserver上下文替换:

public class MyContentObserver extends ContentObserver {
    private Context mContext;
    public MyContentObserver(Handler handler, Context context) {
        super(handler);
        mContext = context;
    }
}

4)。对于BroadcastReceiver(包括内联/嵌入式接收器),使用接收器自己的上下文。

外部BroadcastReceiver:

public class MyBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();
        if (action.equals(Intent.ACTION_SCREEN_OFF)) {
            sendReceiverAction(context, true);
        }
        private static void sendReceiverAction(Context context, boolean state) {
            Intent mIntent = new Intent(context.getClass().getName() + "." + context.getString(R.string.receiver_action));
            mIntent.putExtra("extra", state);
            context.sendBroadcast(mIntent, null);
        }
    }
}

内联/嵌入式BroadcastReceiver:

public class MyActivity extends Activity {
    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final boolean connected = intent.getBooleanExtra(context.getString(R.string.connected), false);
            if (connected) {
                // Do something.
            }
        }
    };
}

5)。对于服务,使用服务自己的上下文。

public class MyService extends Service {
    private BroadcastReceiver mBroadcastReceiver;
    @Override
    public void onCreate() {
        super.onCreate();
        registerReceiver();
    }
    private void registerReceiver() {
        IntentFilter mIntentFilter = new IntentFilter();
        mIntentFilter.addAction(Intent.ACTION_SCREEN_OFF);
        this.mBroadcastReceiver = new MyBroadcastReceiver();
        this.registerReceiver(this.mBroadcastReceiver, mIntentFilter);
    } 
}

6)。对于toast,通常使用getApplicationContext(),但在可能的情况下,使用从活动、服务等传递的上下文。

使用应用程序的上下文:

Toast mToast = Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG);
mToast.show();

使用从源传递的上下文:

public static void showLongToast(Context context, String message) {
    if (context != null && message != null) {
        Toast mToast = Toast.makeText(context, message, Toast.LENGTH_LONG);
        mToast.show();
    }
}

最后,不要像Android框架开发人员建议的那样使用getBaseContext()。

更新:添加上下文使用示例。

简单地说

getApplicationContext()正如方法名称所暗示的那样,将使你的应用程序意识到你可以从应用程序的任何地方访问的应用程序范围的细节。所以你可以在服务绑定,广播注册等中使用它。应用程序上下文将一直存在,直到应用程序退出。

getActivity()或这将使你的应用程序意识到当前屏幕,这也是可见的应用程序上下文提供的应用程序级别的细节。你想知道的关于当前屏幕的任何东西比如Window ActionBar Fragementmanger都可以通过这个context得到。基本上和活动扩展上下文。在当前组件(活动)激活之前,该上下文都是激活的