What's the difference between the various methods to get a Context?

前端 未结 8 589
情书的邮戳
情书的邮戳 2020-11-22 04:06

In various bits of Android code I\'ve seen:

 public class MyActivity extends Activity {
    public void method() {
       mContext = this;    // since Activi         


        
相关标签:
8条回答
  • 2020-11-22 05:10

    Here's what I've found regarding the use of context:

    1) . Within an Activity itself, use this for inflating layouts and menus, register context menus, instantiating widgets, start other activities, create new Intent within an Activity, instantiating preferences, or other methods available in an Activity.

    Inflate layout:

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

    Inflate menu:

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

    Register context menu:

    this.registerForContextMenu(myView);
    

    Instantiate widget:

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

    Start an Activity:

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

    Instantiate preferences:

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

    2) . For application-wide class, use getApplicationContext() as this context exist for the lifespan of the application.

    Retrieve the name of the current Android package:

    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;
        }
    }
    

    Bind an application-wide class:

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

    3) . For Listeners and other type of Android classes (e.g. ContentObserver), use a Context substitution like:

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

    where this or context is the context of a class (Activity, etc).

    Activity context substitution:

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

    Listener context substitution:

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

    ContentObserver context substitution:

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

    4) . For BroadcastReceiver (including inlined/embedded receiver), use the receiver's own context.

    External 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);
            }
        }
    }
    

    Inlined/Embedded 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) . For Services, use the service's own context.

    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) . For Toasts, generally use getApplicationContext(), but where possible, use the context passed from an Activity, Service, etc.

    Use context of the application:

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

    Use context passed from a source:

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

    And last, don't use getBaseContext() as advised by Android's framework developers.

    UPDATE: Add examples of Context usage.

    0 讨论(0)
  • 2020-11-22 05:10

    I read this thread a few days ago, asking myself the same question. My decision after reading this was simple: always use applicationContext.

    However, I encountered a problem with this, I spent a few hours to find it, and a few seconds to solve it... (changing one word...)

    I am using a LayoutInflater to inflate a view containing a Spinner.

    So here are two possibilities:

    1)

        LayoutInflater layoutInflater = LayoutInflater.from(this.getApplicationContext());
    

    2)

        LayoutInflater layoutInflater = LayoutInflater.from(this.getBaseContext());
    

    Then, I am doing something like this:

        // 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);
    

    What I noticed: If you instantiated your linearLayout with the applicationContext, then when you click on the spinner in your activity, you will have an uncaught exception, coming from the dalvik virtual machine (not from your code, that's why I have spent a lot of time to find where was my mistake...).

    If you use the baseContext, then that's all right, the context menu will open and you will be able to choose among your choices.

    So here is my conclusion: I suppose (I have not tested it further) than the baseContext is required when dealing with contextMenu in your Activity...

    The test has been done coding with API 8, and tested on an HTC Desire, android 2.3.3.

    I hope my comment have not bored you so far, and wish you all the best. Happy coding ;-)

    0 讨论(0)
提交回复
热议问题