使用 android 处理程序时如何解决有关内存泄漏的警告?
How can I resolve warnings about memory leaks when using android Handler?
我是初学者android。
我在学习 Thread 时使用的是 Handler。
顺便说一下,我在 android studio 中使用 Handler 来警告内存泄漏。
我搜索了很多不同的问题,但没有与我的情况相对应的部分。
如何解决使用处理程序时有关内存泄漏的警告?
public class HandlerActivity extends AppCompatActivity implements Runnable {
ProgressBar pb;
TextView txtRate;
Button btnStart;
static int value;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.progress);
pb = findViewById(R.id.pb);
txtRate = findViewById(R.id.txtRate);
btnStart = findViewById(R.id.btnStart);
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Thread th = new Thread(HandlerActivity.this);
th.start();
}
});
}
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
pb.setProgress(value);
txtRate.setText("Process : " + value + "%");
}
};
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
value = i;
handler.sendEmptyMessage(0);
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(HandlerActivity.this, "Progress Done !", Toast.LENGTH_SHORT).show();
}
});
}
}
基本上 TextView
或任何其他 View
持有代表相应 Activity
的 Context
对象的引用。当您在 Thread
中保留对任何 View
的强引用时,您不仅存储了 View
对象,而且还存储了一个代表 Activity
创建的 Context
对象它。现在,由于 Thread
与 Activity 生命周期无关,即使在 Activity
被销毁后,它们仍将继续 运行。如果是这种情况,Thread
将通过那个 View
对象持有一个被破坏的 Activity
的引用,从而造成内存泄漏。
上述问题可以通过存储View
对象的弱引用来解决,以便GC在必要时对其进行垃圾回收。您可以通过以下方式消除内存泄漏:
public class HandlerActivity extends AppCompatActivity implements Runnable {
WeakReference<ProgressBar> pb;
WeakReference<TextView> txtRate;
Button btnStart;
static int value;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
pb = new WeakReference<>(findViewById(R.id.pb)); // you may require to cast findViewById() to ProgressBar
txtRate = new WeakReference<>(findViewById(R.id.txtRate)); // you may require to cast findViewById() to TextView
...
}
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(pb.get()!=null) pb.get().setProgress(value);
if(txtRate.get()!=null) txtRate.get().setText("Process : " + value + "%");
}
};
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
// Its always recommended to check if activity is running and stop the thread if not running
if(isFinishing() || isDestroyed()) {
return;
}
}
}
}
Roaim, Mark Keen 在他们的帮助下,我解决了这个问题并自己给出了完整的答案。感谢 Roaim、Mark Keen。
public class HandlerActivity extends AppCompatActivity implements Runnable {
ProgressBar pb;
TextView txtRate;
Button btnStart;
int value;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.progress);
pb = findViewById(R.id.pb);
txtRate = findViewById(R.id.txtRate);
btnStart = findViewById(R.id.btnStart);
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Thread th = new Thread(HandlerActivity.this);
th.start();
}
});
}
private static class WeakHandler extends Handler {
private final WeakReference<HandlerActivity> mWeakActivity;
private WeakHandler(HandlerActivity AppCompatActivity) {
mWeakActivity = new WeakReference<>(AppCompatActivity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
HandlerActivity _activity = mWeakActivity.get();
if (_activity != null) {
switch (msg.what) {
case 0:
_activity.pb.setProgress(_activity.value);
_activity.txtRate.setText("Process : " + _activity.value + "%");
break;
}
}
}
}
private final WeakHandler mHandler = new WeakHandler(this);
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
value = i;
mHandler.sendEmptyMessage(0);
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(HandlerActivity.this, "Progress Done !.", Toast.LENGTH_SHORT).show();
}
});
}
}
我是初学者android。 我在学习 Thread 时使用的是 Handler。 顺便说一下,我在 android studio 中使用 Handler 来警告内存泄漏。 我搜索了很多不同的问题,但没有与我的情况相对应的部分。 如何解决使用处理程序时有关内存泄漏的警告?
public class HandlerActivity extends AppCompatActivity implements Runnable {
ProgressBar pb;
TextView txtRate;
Button btnStart;
static int value;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.progress);
pb = findViewById(R.id.pb);
txtRate = findViewById(R.id.txtRate);
btnStart = findViewById(R.id.btnStart);
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Thread th = new Thread(HandlerActivity.this);
th.start();
}
});
}
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
pb.setProgress(value);
txtRate.setText("Process : " + value + "%");
}
};
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
value = i;
handler.sendEmptyMessage(0);
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(HandlerActivity.this, "Progress Done !", Toast.LENGTH_SHORT).show();
}
});
}
}
基本上 TextView
或任何其他 View
持有代表相应 Activity
的 Context
对象的引用。当您在 Thread
中保留对任何 View
的强引用时,您不仅存储了 View
对象,而且还存储了一个代表 Activity
创建的 Context
对象它。现在,由于 Thread
与 Activity 生命周期无关,即使在 Activity
被销毁后,它们仍将继续 运行。如果是这种情况,Thread
将通过那个 View
对象持有一个被破坏的 Activity
的引用,从而造成内存泄漏。
上述问题可以通过存储View
对象的弱引用来解决,以便GC在必要时对其进行垃圾回收。您可以通过以下方式消除内存泄漏:
public class HandlerActivity extends AppCompatActivity implements Runnable {
WeakReference<ProgressBar> pb;
WeakReference<TextView> txtRate;
Button btnStart;
static int value;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
pb = new WeakReference<>(findViewById(R.id.pb)); // you may require to cast findViewById() to ProgressBar
txtRate = new WeakReference<>(findViewById(R.id.txtRate)); // you may require to cast findViewById() to TextView
...
}
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(pb.get()!=null) pb.get().setProgress(value);
if(txtRate.get()!=null) txtRate.get().setText("Process : " + value + "%");
}
};
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
// Its always recommended to check if activity is running and stop the thread if not running
if(isFinishing() || isDestroyed()) {
return;
}
}
}
}
Roaim, Mark Keen 在他们的帮助下,我解决了这个问题并自己给出了完整的答案。感谢 Roaim、Mark Keen。
public class HandlerActivity extends AppCompatActivity implements Runnable {
ProgressBar pb;
TextView txtRate;
Button btnStart;
int value;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.progress);
pb = findViewById(R.id.pb);
txtRate = findViewById(R.id.txtRate);
btnStart = findViewById(R.id.btnStart);
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Thread th = new Thread(HandlerActivity.this);
th.start();
}
});
}
private static class WeakHandler extends Handler {
private final WeakReference<HandlerActivity> mWeakActivity;
private WeakHandler(HandlerActivity AppCompatActivity) {
mWeakActivity = new WeakReference<>(AppCompatActivity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
HandlerActivity _activity = mWeakActivity.get();
if (_activity != null) {
switch (msg.what) {
case 0:
_activity.pb.setProgress(_activity.value);
_activity.txtRate.setText("Process : " + _activity.value + "%");
break;
}
}
}
}
private final WeakHandler mHandler = new WeakHandler(this);
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
value = i;
mHandler.sendEmptyMessage(0);
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(HandlerActivity.this, "Progress Done !.", Toast.LENGTH_SHORT).show();
}
});
}
}