Handler内存泄漏-解决:使用静态类和弱引用

//    private Handler mHandler=new Handler(){//导os包
//        @Override
//        public void handleMessage(Message msg) {
//            super.handleMessage(msg);
//            switch (msg.what){
//                case 1:
//
//                    break;
//
//                case 2:
//
//                    break;
//
//            }
//        }
//    };

Activity这样使用Handler会存在内存泄漏的问题
解决:
1Handler使用静态内部类创建 2对所持有的Activity引用变为弱引用
原因:
1在Java 中,非静态的内部类和匿名内部类都会隐式地持有其外部类的引用,静态的内部类不会持有外部类的引用。
2由于Handler不再持有外部类对象的引用,导致程序不允许你在Handler中操作Activity中的对象了。所以你需要在Handler中增加一个对Activity的弱引用(WeakReference)。

//创建静态内部类
private static class MyHandler extends Handler {
    //持有弱引用MainActivity,GC回收时会被回收掉.
    WeakReference<OkhttpTestActivity> mWeakReference;
    private MyHandler(OkhttpTestActivity mainActivity) {
        mWeakReference = new WeakReference<>(mainActivity);
    }
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        switch (msg.what)
        {
            case 1:
                if(mWeakReference.get()!=null){
                    mWeakReference.get().mTv.setText(msg.getData().getString("response"));
                }else {
                    Log.e("wy","Activity销毁,弱引用也随之销毁");
                }
                break;
            case 2:
                break;

        }
    }


}
Handler handler = new MyHandler(this);

子线程中发送消息

Bundle mBundle= new Bundle();
mBundle.putString("response",response.toString());
Message msg=Message.obtain();
msg.what=1;
msg.setData(mBundle);
handler.sendMessage(msg);

使用okhttp异步请求进行网络访问,全代码

implementation("com.squareup.okhttp3:okhttp:4.8.1")
package com.wintec.netframworktest;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;

import java.io.IOException;
import java.lang.ref.WeakReference;

import androidx.appcompat.app.AppCompatActivity;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;


public class OkhttpTestActivity extends AppCompatActivity {
    OkHttpClient client;
    private  TextView mTv;
    //创建静态内部类
    private static class MyHandler extends Handler {
        //持有弱引用MainActivity,GC回收时会被回收掉.
        WeakReference<OkhttpTestActivity> mWeakReference;
        private MyHandler(OkhttpTestActivity mainActivity) {
            mWeakReference = new WeakReference<>(mainActivity);
        }
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what)
            {
                case 1:
                    if(mWeakReference.get()!=null){
                        mWeakReference.get().mTv.setText(msg.getData().getString("response"));
                    }else {
                        Log.e("wy","Activity销毁,弱引用也随之销毁");
                    }
                    break;
                case 2:
                    break;

            }
        }


    }
    Handler handler = new MyHandler(this);

//@SuppressLint("HandlerLeak")
//    private Handler mHandler=new Handler(){//导os包
//        @Override
//        public void handleMessage(Message msg) {
//            super.handleMessage(msg);
//            switch (msg.what){
//                case 1:
//
//                    break;
//
//                case 2:
//
//                    break;
//
//            }
//        }
//    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTv = (TextView) findViewById(R.id.tv);
        Request request = new Request.Builder()
                .url("https://wap.peopleapp.com/article/5933922/5852020")
                .build();

         client = new OkHttpClient();
//         OkHttp的同步请求会阻塞当前线程,因此不能在UI线程中请求,需要开启子线程,在子线程中发送请求。

//         new Thread(new Runnable() {
//             @Override
//             public void run() {
//                 try {
//                     Log.e("wy","okhttp同步请求返回: "+ client.newCall(request).execute().toString());
//                     mTv.setText(client.newCall(request).execute().toString());
//                 } catch (IOException mE) {
//                     mE.printStackTrace();
//                 }
//             }
//         }).start();

//         异步请求
        Call call=client.newCall(request);
        call.enqueue(new Callback() {

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.e("wy","okhttp异步请求response返回:"+response.toString());
//                android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
//                mTv.setText(response.toString());
//                使用Handler进行线程通讯

                Bundle mBundle= new Bundle();
                mBundle.putString("response",response.toString());
                Message msg=Message.obtain();
                msg.what=1;
                msg.setData(mBundle);
                handler.sendMessage(msg);


//                OkhttpTestActivity.this.runOnUiThread(new Runnable() {
//                    public void run() {
//                        mTv.setText(response.toString());
//                    }
//                });
            }
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e("wy","okhttp异步请求异常:"+e);
            }
        });

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        handler.removeCallbacksAndMessages(null);
    }
}

在我们以后开发中使用handler时,就可以使用静态类和弱引用,这样可以避免内存泄漏现象,达到内存优化的目的。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值