What's the difference between the various ways to get context?

Keywords: Android Google SDK

Among the various Android codes I've seen:

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

However, I couldn't find any suitable explanation for what was better and in what circumstances it should be used.

Instructions for documentation in this regard, as well as guidance on possible damage if the wrong one is chosen, will be appreciated.

#1 building

I agree that there are few documents when using Contexts in Android, but you can put together some facts from various sources.

This blog post Google's official Android Developer blog is mainly written to help solve memory leaks, but provides some useful information about the context, as well as:

In general Android applications, there are usually two kinds of Context, Activity and Application.

When you read the article a little bit more about the difference between the two, you may want to consider using the application context (Activity.getApplicationContext() instead of this). Basically, the application context is associated with the application and is always the same throughout the life of the application because the activity context is associated with the activity and may be destroyed multiple times during a screen orientation change when the activity is destroyed. This way.

I can't find anything about when to use getBaseContext() instead of a post from Dianne Hackborn, a Google engineer working on the Android SDK:

Don't use getBaseContext (), just use the Context you own.

This is from Android developers newsgroup You may also want to consider asking your questions there, because a few people working on Android actually monitor newsgroups and answer questions.

Overall, it seems best to use the global application context where possible.

#2 building

Here is what I found about the use of context:

1). In Activity itself, use this to expand layout and menu, register context menu, instantiate widget, start other activities, create new Intent in Activity, instantiate preferences or other methods available to Activity.

Inflation layout:

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

Expansion 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 Activity:

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

Instantiation preferences:

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

2). For application scoped classes, use getApplicationContext() because this context exists in the application's lifecycle.

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

Bound application wide classes:

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 types of Android classes (such as ContentObserver), use Context instead, such as:

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

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

Activity context replacement:

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

Listener context replacement:

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

ContentObserver context replacement:

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

4). For BroadcastReceiver (including inline / embedded receivers), 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);
        }
    }
}

Inline / 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 context of the service itself.

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 toast, getApplicationContext() is usually used, but where possible, the context passed from Activity, Service, etc.

Use the context of the application:

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

Use context passed from 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();
    }
}

Finally, don't use getBaseContext() like an Android Framework Developer.

Update: add an example of Context usage.

#3 building

First of all, I agree that we should use appcontext as much as possible. Then "this" in the activity. I never needed basecontext.

In my tests, they were interchangeable in most cases. In most cases, the reason you want to get context is to access files, preferences, databases, and so on. The data is eventually reflected as files in the application's private data folder (/ data / data /). No matter what context you use, they map to the same folder / file so you can.

That's what I observed. Maybe there are situations where you should distinguish between them.

#4 building

In some cases, you can use the Activity context when running something in a thread instead of the application context when the thread finishes executing and you need to return the result to the caller Activity.

((YourActivity) context).yourCallbackMethod(yourResultFromThread, ...);

#5 building

Simply speaking

getApplicationContext() as the method name recommendation will let your application know the details of the application scope that you can access from anywhere in the application. Therefore, you can use it in service binding, broadcast registration, etc. Application context will remain until the application exits.

getActivity() or this will let your application understand the current screen, which can also see the application context program level details provided by the application context. Therefore, you can use this Context whether you want to know the current screen, such as window actionbar framementmanger, etc. Basically extend Context with Activity. This Context will remain until the current component (Activity) is active

Posted by Barkord on Tue, 11 Feb 2020 05:01:24 -0800