Android-обработчик изменяет WeakReference
Мой статический обработчик имеет WeakReference
к моему Activity
(это должно предотвратить хорошо документированную проблему утечки памяти).
Я публикую длинное сообщение с задержкой и хочу, чтобы это сообщение было доставлено в мою деятельность (что должно быть на переднем плане).
Меня беспокоит то, что при изменении ориентации моя активность уничтожается, и у обработчика есть ссылка на старую активность, которая должна была быть уничтожена.
Для того, чтобы обойти это в моем onCreate
для деятельности я делаю это.
if(mHandler == null)
mHandler = new LoginHandler(this);
else {
mHandler.setTarget(this);
}
И мой обработчик объявлен как статическая глобальная переменная:
private static LoginHandler mHandler = null;
и реализующий класс также является статическим, как показано ниже:
private static class LoginHandler extends Handler {
private WeakReference<LoginActivity> mTarget;
LoginHandler(LoginActivity target) {
mTarget = new WeakReference<LoginActivity>(target);
}
public void setTarget(LoginActivity target) {
mTarget = new WeakReference<LoginActivity>(target);
}
@Override
public void handleMessage(Message msg) {
// process incoming messages here
LoginActivity activity = mTarget.get();
switch (msg.what) {
case Constants.SUCCESS:
activity.doSomething();
break;
default:
activity.setStatusMessage("failed " + msg.obj, STATUS_TYPE_DONE);
}
}
}
Я хочу знать, есть ли что-то не так с изменением WeakReference на onCreate
или что-то еще не так с этим подходом?
Спасибо,
2 ответа
Поэтому я написал следующий тест, чтобы выяснить, правильно ли я понял или нет, и кажется, что подход m верен. В onCreate
мы меняем WeakReference
и опубликованное сообщение всегда будет доставлено в действие, которое находится на переднем плане. Если вы измените этот код, чтобы всегда создавать новый обработчик в onCreate
вы заметите, что сообщения об обновлении не доставляются.
public class MainActivity extends Activity {
private static int COUNT = 0;
static LoginHandler mHandler;
private static class LoginHandler extends Handler {
private WeakReference<MainActivity> mTarget;
LoginHandler(MainActivity target) {
mTarget = new WeakReference<MainActivity>(target);
}
public void setTarget(MainActivity target) {
mTarget.clear();
mTarget = new WeakReference<MainActivity>(target);
}
@Override
public void handleMessage(Message msg) {
// int duration = Toast.LENGTH_LONG;
// process incoming messages here
MainActivity activity = mTarget.get();
activity.update(msg.arg1);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(mHandler == null)
mHandler = new LoginHandler(this);
else
mHandler.setTarget(this);
((Button)findViewById(R.id.button)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Message msg = new Message();
msg.arg1 = COUNT++;
mHandler.sendMessageDelayed(msg, 3000);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private void update(int count) {
((TextView) findViewById(R.id.hello_world)).setText("Hello World @ "+ count);
}
}
Если вы хотите сохранить активные объекты, если вы хотите сохранить активные объекты, вы можете использовать "Сохраняющиеся фрагменты".
Идея проста: вы говорите системе Android "сохранить" ваш фрагмент, когда связанная с ним деятельность уничтожается и создается заново. И убедитесь, что вы захватили контекст текущего действия в вызываемом фрагменте onAttach(), чтобы вы всегда обновляли правильное действие.
Ниже ссылка имеет более подробную информацию: http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html