西部数码主机 | 阿里云主机| 虚拟主机 | 服务器 | 返回乐道官网

Android优雅地发起网络Request与接收Response

时间:2016-04-04 21:15来源:未知 作者:好模板 点击:
Android发起网络Request与接收Response以下几种写法很常见: 1、直接 new Thread 进行请求,数据返回后使用 handler 回到主线程进行 UI 刷新。 private void getData() { new Thread(new Runnable() { @Override p

Android发起网络Request与接收Response以下几种写法很常见:

1、直接 new Thread 进行请求,数据返回后使用 handler 回到主线程进行 UI 刷新。

private void getData() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                final String result = GetDataHelper.getData();
                ShowImageActivity.this.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        // 处理结果,更新 UI
                    }
                });
            }
        }).start();
    }

2、或 直接 new AsyncTask。

private void getData() {
        new AsyncTask<String, String, String>(){

            @Override
            protected String doInBackground(String... params) {
                String retult = GetDataHelper.getData();
                return retult;
            }

            @Override
            protected void onPostExecute(String result) {
                // 处理结果,更新 UI
            }
        }.execute("params");
    }

3、使用封装好的网络请求库

JsonObjectRequest jsonObjectRequest = new JsonObjectRequest("api", null,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        Log.d("TAG", response.toString());
                    }
                }, new Response.ErrorListener() {
            
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e("TAG", error.getMessage(), error);
            }
        });

问题来了,就是面试被问烂了的 匿名内部类隐式地持有其外部类的引用 ,在内部类的生命比外部类的生命要长的情景下会引起内存泄露。

面试者都会说,使用 静态内部类 可以解决这个问题,在这里就不再多说,具体解决可参考技术小黑屋的:

Android 中 Handler 引起的内存泄露

面试时大家都会说使用静态内部类代替非静态内部类和匿名内部类,但为什么以上几种会引起内存泄露的写法还是这么多人用、在项目中还是那么常见呢?

静态内部类繁琐?

不介意短暂的内存泄露?反正响应返回或超时后都会释放?

以上写法除了内存泄露问题,还存在缺乏线程管理、统一调度,耦合等问题。

还有没更优雅的做法?

API 请求中心化管理,提供静态方法给外部调用,不设置回调函数(回调引用一样会引起内存泄露),使用事件总线(EventBus、otto 或 自己写)进行响应的结果分发,观察者在生命周期注册与反注册事件监听。

public class APIManager {

    private static RequestQueue mQueue;

    public void init(Context context){
        mQueue  = Volley.newRequestQueue(context);
    }

    public static void register(String username, String psw){
        //do register
    }

    public static void login(String username, String psw){
        //do login
    }

    public static void getData(){
        String getDataUrl = "XXXXX";
        JsonObjectRequest request = creatJsonObjectRequest(getDataUrl, null, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                GetDataEvent event = new GetDataEvent(0, response.toString());
                EventBus.getDefault().post(event);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                GetDataEvent event = new GetDataEvent(-1, error.getMessage());
                EventBus.getDefault().post(event);
            }
        });
        mQueue.add(request);
    }

    private static JsonObjectRequest creatJsonObjectRequest(String url, JSONObject requestObject, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener){
        return new JsonObjectRequest(url, requestObject, listener, errorListener);
    }
}

API 请求中心化管理,这里以 Volley 为例。若是自己封装的网络请求,也可以自定义线程池去管理线程。

提供静态方法 getData() 给外部调用,不需传入回调函数,与外部脱离引用关系,解耦。请求响应后使用事件总线(这里以 EventBus 为例)分发响应结果事件EventBus.getDefault().post(event)

观察者,这里即当前 Activity

@Override
    protected void onResume() {
        super.onResume();
        // 注册监听
        EventBus.getDefault().register(this);
    }

    @Override
    protected void onStop() {
        // 反注册监听
        EventBus.getDefault().unregister(this);
        super.onStop();
    }

    @Subscribe
    public void onMessageEvent(GetDataEvent event){
        int errorCode = event.getErrorCode();
        String message = event.getMessage();
    }

在生命周期注册与反注册事件监听,设置监听响应函数。

private void getData() {
        APIManager.getData();
    }

需要请求可直接调用 API 管理中心提供的静态请求方法。

中心化管理 API,避免内存泄露,完美解耦

前两天实现了一个需求,在某一具体页面,发起网络请求后,无论用户是否还是发起请求页面,还是已经回退到之前的页面,只要请求响应,都需要在当前页面弹出一个 Dialog。

解耦发挥作用,只需要在全部页面(BaseActivity)注册监听这个请求的响应事件即可。

(责任编辑:好模板)
顶一下
(1)
100%
踩一下
(0)
0%
------分隔线----------------------------
栏目列表
热点内容