获取上下文的各种方法之间有什么区别?

Aln*_*tak 387 android android-context

在我看过的各种Android代码中:

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

但是,我找不到任何合适的解释,哪些更好,以及在什么情况下应该使用.

关于这方面的文件的指示,以及关于如果选择了错误的可能会破坏的指导,将不胜感激.

snc*_*tln 303

我同意在Android中使用Contexts时文档很少,但您可以将各种来源的一些事实拼凑起来.

本博客文章在谷歌官方Android开发者博客写主要是为了帮助解决内存泄漏,但提供了有关上下文一些有用的信息,以及:

在常规Android应用程序中,通常有两种Context,Activity和Application.

阅读文章稍微进一步讲述了两者之间的区别以及何时可能要考虑使用应用程序Context(Activity.getApplicationContext())而不是使用Activity上下文this.基本上,应用程序上下文与应用程序相关联,并且在应用程序的整个生命周期中始终是相同的,因为活动上下文与活动相关联,并且可能会在屏幕方向更改期间销毁活动时多次销毁.这样.

我找不到什么关于什么时候使用getBaseContext(),而不是来自Dianne Hackborn的帖子,Dianne Hackborn是一位在Android SDK上工作的Google工程师:

不要使用getBaseContext(),只需使用你拥有的Context.

这是来自android-developers新闻组的帖子,你可能也想考虑在那里问你的问题,因为在Android上工作的少数人实际监控新闻组并回答问题.

总的来说,似乎最好在可能的情况下使用全局应用程序上下文.

  • 当我有一个活动A,它可以启动活动B,反过来,可以用CLEAR_TOP标志重启A(并可能多次重复这个循环) - 在这种情况下我应该使用什么上下文,以避免建立一个巨大的引用的上下文?Diana说使用'this'而不是getBaseContext,但是......大多数时候A会被重用,但有时会创建A的新对象,然后旧的A泄漏.所以似乎getBaseContext是大多数情况下最合适的选择.然后不清楚为什么`不要使用getBaseContext()`.有人可以澄清一下吗? (12认同)
  • 如何访问不扩展Activity的类内部的上下文对象? (2认同)

Chu*_*ham 53

以下是我发现的使用context:

1).在其Activity自身内,this用于膨胀布局和菜单,注册上下文菜单,实例化窗口小部件,启动其他活动,在其中创建新IntentActivity,实例化首选项或其他可用的方法Activity.

充气布局:

View mView = this.getLayoutInflater().inflate(R.layout.myLayout, myViewGroup);
Run Code Online (Sandbox Code Playgroud)

膨胀菜单:

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

注册上下文菜单:

this.registerForContextMenu(myView);
Run Code Online (Sandbox Code Playgroud)

实例化小部件:

TextView myTextView = (TextView) this.findViewById(R.id.myTextView);
Run Code Online (Sandbox Code Playgroud)

开始Activity:

Intent mIntent = new Intent(this, MyActivity.class);
this.startActivity(mIntent);
Run Code Online (Sandbox Code Playgroud)

实例化首选项:

SharedPreferences mSharedPreferences = this.getPreferenceManager().getSharedPreferences();
Run Code Online (Sandbox Code Playgroud)

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

绑定应用程序范围的类:

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

3).对于Listeners和其他类型的Android类(例如ContentObserver),使用Context替换,如:

mContext = this;    // Example 1
mContext = context; // Example 2
Run Code Online (Sandbox Code Playgroud)

在哪里this或是context类的上下文(Activity等).

Activity 上下文替换:

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

监听器上下文替换:

public class MyLocationListener implements LocationListener {
    private Context mContext;
    public MyLocationListener(Context context) {
        mContext = context;
    }
}
Run Code Online (Sandbox Code Playgroud)

ContentObserver 上下文替换:

public class MyContentObserver extends ContentObserver {
    private Context mContext;
    public MyContentObserver(Handler handler, Context context) {
        super(handler);
        mContext = context;
    }
}
Run Code Online (Sandbox Code Playgroud)

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

内联/嵌入式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.
            }
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

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);
    } 
}
Run Code Online (Sandbox Code Playgroud)

6).对于Toasts,通常使用getApplicationContext(),但在可能的情况下,使用从Activity,Service等传递的上下文.

使用应用程序的上下文:

Toast mToast = Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG);
mToast.show();
Run Code Online (Sandbox Code Playgroud)

使用从源传递的上下文:

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

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

更新:添加Context用法示例.

  • +1这样一个有用的答案!我同意接受的答案很好,作为公认的答案,但圣洁的莫莉这个答案是超级信息!感谢所有这些示例,它们帮助我更好地理解整体上下文的使用.我甚至将你的答案复制到我机器上的文本文件中作为参考. (3认同)

小智 12

我几天前读过这个帖子,问自己同样的问题.我在阅读之后的决定很简单:始终使用applicationContext.

但是,我遇到了这个问题,我花了几个小时找到它,并花了几秒钟来解决它......(换一个字......)

我使用LayoutInflater来膨胀包含Spinner的视图.

所以这里有两种可能性:

1)

    LayoutInflater layoutInflater = LayoutInflater.from(this.getApplicationContext());
Run Code Online (Sandbox Code Playgroud)

2)

    LayoutInflater layoutInflater = LayoutInflater.from(this.getBaseContext());
Run Code Online (Sandbox Code Playgroud)

然后,我正在做这样的事情:

    // managing views part
    View view = ContactViewer.mLayoutInflater.inflate(R.layout.aViewContainingASpinner, theParentView, false);
    Spinner spinner = (Spinner) view.findViewById(R.id.theSpinnerId);
    String[] myStringArray = new String[] {"sweet","love"};

    // managing adapter part
    // The context used here don't have any importance -- both work.
    ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this.getApplicationContext(), myStringArray, android.R.layout.simple_spinner_item);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner.setAdapter(adapter);

    theParentView.addView(view);
Run Code Online (Sandbox Code Playgroud)

我注意到的:如果你使用applicationContext实例化你的linearLayout,那么当你点击你活动中的微调器时,你会得到一个未被捕获的异常,来自dalvik虚拟机(不是来自你的代码,这就是我花了很多钱的原因)时间找到我的错误...).

如果您使用baseContext,那就没问题,上下文菜单将打开,您可以在您的选择中进行选择.

所以这是我的结论:我想(我还没有进一步测试)比在Activity中处理contextMenu时需要baseContext ...

该测试已经使用API​​ 8进行了编码,并在HTC Desire,android 2.3.3上进行了测试.

我希望我的评论到目前为止还没有让你厌烦,并祝你一切顺利.快乐的编码;-)


小智 6

首先,我同意我们应尽可能使用appcontext.然后在活动中"这个".我从来没有需要basecontext.

在我的测试中,在大多数情况下,它们可以互换.在大多数情况下,您希望获取上下文的原因是访问文件,首选项,数据库等.这些数据最终会反映为应用程序私有数据文件夹(/ data/data /)中的文件.无论您使用哪种上下文,它们都会映射到相同的文件夹/文件,这样您就可以了.

这就是我观察到的.也许有些情况你应该区分它们.