Context là thành phần trong ứng dụng android cung cấp quyền truy cập thông tin về các trạng thái của ứng dụng đó. Nó cung cấp các Activities, Fragments và Services truy cập tới các file tài nguyên, hình ảnh, theme, style và các file nằm ngoài ứng dụng. Nó cũng cho phép truy cập vào các thành phần chính của Android như layout, keyboard và tìm kiếm các content providers.
Trong nhiều trường hợp, khi bắt buộc phải sử dụng Context chúng ta đơn giản truyền vào instance của activity hiện tại. Trong tình huống chúng ta ở trong các object được tạo bởi activity như adapter của fragments, chúng ta cần truyền activity instance vào trong object đó. Còn trong trường hợp chúng ta ở ngoài activity đó (VD application, service), chúng ta sẽ sử dụng "application" context thay thể.
Sẽ có các trường hợp nhất định bắt buộc phải truyền vào context, ví dụ như start một activity, tạo một view mới, gửi local broadcast..v..v..
Như chúng ta đã biết, Application Context và Activity Context là 2 thành phần context cơ bản nhất của Android. Vậy chúng khác nhau như thế nào?
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/MyCustomTheme">
Đa phần các View nên truyền vào Activity Context để có thể apply các theme,style, dimensions tự định nghĩa. Nếu ko có trường hợp nào định nghĩa riêng cho Activity, default sẽ là trường hợp định nghĩa riêng cho Application. Đa số các trường hợp bạn nên sử dụng Activity Context, thông thường keyword this là instance của class cũng đại diện cho Activity Context.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
TextView tvTest = (TextView) findViewById(R.id.abc);
tvTest.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MainActivity.this, "Chiu chiu", Toast.LENGTH_SHORT).show();
}
});
}
}
Application Context là điển hình của Singleon instance, giống như class custom manager cần Context thông tin để có quyền truy cập vào system service nhưng sẽ được tái sử dụng ở nhiều Activity. Việc tham chiếu đến Activity Context sẽ không tự giải phóng bộ nhớ khi không dùng đến, đó là 1 trong lý do ta dùng Application Context để thay thế trong trường hợp trên. Ví dụ dưới đây, context sẽ được chứa ở Activity hoặc Service và destroy bởi hệ thống. Nó sẽ ko được giải phóng bộ nhớ bởi CustomeManager class giữ một tham chiếu static đến nó
public class CustomManager {
private static CustomManager sInstance;
public static CustomManager getInstance(Context context) {
if (sInstance == null) {
// This class will hold a reference to the context
// until it's unloaded. The context could be an Activity or Service.
sInstance = new CustomManager(context);
}
return sInstance;
}
private Context mContext;
private CustomManager(Context context) {
mContext = context;
}
}
Vây để xử lý những trường hợp trên, không bao giờ được giữ tham chiếu đến context ngoài vòng đời của nó. Kiểm tra mọi background thread, pending handler , hoặc inner class. Sử dụng Application Context khi nó cần tham chiếu xuyên suốt theo vòng đời của component. VD như để giải quyết trường hợp trên như sau
public static CustomManager getInstance(Context context) {
if (sInstance == null) {
// When storing a reference to a context, use the application context.
// Never store the context itself, which could be a component.
sInstance = new CustomManager(context.getApplicationContext());
}
return sInstance;
}
Unpublished comment
Viết câu trả lời