Android通用网络请求解析框架.8(同步请求,分支部分)

19 篇文章 0 订阅
14 篇文章 0 订阅
笔者将通过11篇博客对个人开源框架进行讲解,本篇为第8篇,讲解支持同步请求,分支部分。


如果有兴趣一起讨论本框架的内容,请加QQ群:271335749



上一篇中我们已经完成了同步请求公共部分的代码实现,核心监听器的代码是这样的
abstract public class SyncNetHandleListener implements SyncNetListener {
    protected NetRetBean handleResult(NetRetBean netRetBean) {
        return netRetBean;
    }

    @Override
    public NetRetBean sendSuccess(String result) {
        NetRetBean netRetBean = new NetRetBean();
        try {
            JSONObject jsonObject = new JSONObject(result);
            String code = jsonObject.getString("code");
            String message = jsonObject.getString("message");
            String time = jsonObject.getString("time");
            String data = jsonObject.getString("data");
            netRetBean.setServerCode(code);
            netRetBean.setServerMsg(message);
            netRetBean.setServerTime(time);
            netRetBean.setServerData(data);
            if (code.equals("00001")) {
                netRetBean.setCallbackCode(CallbackCode.CODE_SUCCESS_REQUEST);
                netRetBean = onReceivedRet(netRetBean);
            } else {
                netRetBean.setCallbackCode(CallbackCode.CODE_ERROR_SERVER_DATA_ERROR);
            }
        } catch (JSONException e) {
            e.printStackTrace();
            netRetBean.setCallbackCode(CallbackCode.CODE_ERROR_JSON_EXP);
        }
        return handleResult(netRetBean);
    }

    @Override
    public NetRetBean sendError(Exception exp) {
        exp.printStackTrace();

        NetRetBean netRetBean = new NetRetBean();
        netRetBean.setException(exp);

        try {
            throw exp;
        } catch (RespondErrorException e) {
            netRetBean.setCallbackCode(CallbackCode.CODE_ERROR_HTTP_NOT_200);
        } catch (RequestErrorException e) {
            netRetBean.setCallbackCode(CallbackCode.CODE_ERROR_REQUEST_EXP);
        } catch (JSONException e) {
            netRetBean.setCallbackCode(CallbackCode.CODE_ERROR_JSON_EXP);
        } catch (Exception e) {
            netRetBean.setCallbackCode(CallbackCode.CODE_ERROR_UNKNOWN);
        }

        return handleResult(netRetBean);
    }

    abstract protected NetRetBean onReceivedRet(NetRetBean netRetBean) throws JSONException;
}

使用上SyncNetHandleListener,会是这样的
private void syncGetString() {
    new Thread() {
        @Override
        public void run() {
            NetRetBean netRetBean = NetHelper.getSync("url", new SyncNetHandleListener() {
                @Override
                protected NetRetBean onReceivedRet(NetRetBean netRetBean) throws JSONException {
                    return null;
                }
            });
        }
    }.start();
}

还是存在代码执行顺序模糊的问题。还有内层数据的解析,需要开发者自己来完成。
如果在onReceivedRet回调的解析方法中直接返回null,那么在返回的NetRetBean的内层数据还是为null。

为了不让使用者来实现内层数据的解析,所以就应该在框架内部实现内层数据的解析。
那应该怎样在框架内部进行解析呢?学异步请求就好了,继承SyncNetHandleListener,来看看子类中是怎样解析数据的
package com.chenjian.net.listener.sync;

import com.chenjian.net.bean.NetRetBean;

import org.json.JSONException;

/**
 * 返回字String的网络请求Listener
 * <p>
 * 作者: ChenJian
 * 时间: 2016.12.15 14:54
 */

public class SyncNetStringListener extends SyncNetHandleListener {

    @Override
    protected NetRetBean onReceivedRet(NetRetBean netRetBean) throws JSONException {
        netRetBean.setServerObject(netRetBean.getServerData());
        return handleResult(netRetBean);
    }
}

这里的handleResult是父类的方法,根据之前的代码,父类这个方法只是将NetRetBean原封不动的返回。
因为父类中定义抽象方法onReceivedRet时需要返回值,所以这里需要将内层数据进行解析,然后再返回。
还有一个变化,因为本类不存在抽象方法,所以本类也不是抽象类了,不要在类的前面加上abstract。

对比一下异步请求的代码实现
abstract public class NetStringListener extends NetHandleListener {

    @Override
    protected void onReceivedRet(NetRetBean netRetBean) throws JSONException {
        netRetBean.setServerObject(netRetBean.getServerData());
        handleResult(netRetBean);
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void onSuccess(CallbackCode successCode, NetRetBean netRetBean) {
        onSuccess((String) netRetBean.getServerObject());
    }

    /**
     * 运行在ui线程,返回单个实体
     *
     * @param string 当前string
     */
    abstract protected void onSuccess(String string);
}

可以看到,同步请求的时候,因为父类没有onSuccess方法,也不需要回调,所以同步请求代码实现起来更简单,只是将解析后的结果进行返回就可以了。
正如上面所说,同步请求的Listener不是抽象类,不要加abstract修饰类,


其它监听器也需要做类似的修改,继承SyncNetHandleListener,我们实现了SyncNetSingleBeanListener
package com.chenjian.net.listener.sync;

import com.chenjian.net.bean.NetBaseBean;
import com.chenjian.net.bean.NetRetBean;
import com.chenjian.net.util.NetBaseBeanUtil;

import org.json.JSONException;
import org.json.JSONObject;

/**
 * 返回是单个Bean的网络请求Listener
 * <p>
 * 作者: ChenJian
 * 时间: 2016.12.15 14:54
 */

public class SyncNetSingleBeanListener<T extends NetBaseBean> extends SyncNetHandleListener {

    @Override
    protected NetRetBean onReceivedRet(NetRetBean netRetBean) throws JSONException {
        JSONObject object = new JSONObject(netRetBean.getServerData());
        T t = NetBaseBeanUtil.parseItem(getClass(), 0, object);
        netRetBean.setServerObject(t);
        return handleResult(netRetBean);
    }
}

再实现SyncNetListBeanListener
package com.chenjian.net.listener.sync;

import com.chenjian.net.bean.NetBaseBean;
import com.chenjian.net.bean.NetRetBean;
import com.chenjian.net.util.NetBaseBeanUtil;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

/**
 * 返回是List<Bean>的网络请求Listener
 * <p>
 * 作者: ChenJian
 * 时间: 2016.12.15 14:54
 */

public class SyncNetListBeanListener<T extends NetBaseBean> extends SyncNetHandleListener {

    @Override
    protected NetRetBean onReceivedRet(NetRetBean netRetBean) throws JSONException {
        JSONArray array = new JSONArray(netRetBean.getServerData());
        List<T> list = new ArrayList<>();
        for (int i = 0; i < array.length(); i++) {
            JSONObject object = array.getJSONObject(i);
            T t = NetBaseBeanUtil.parseItem(getClass(), 0, object);
            list.add(t);
        }
        netRetBean.setServerObject(list);
        return handleResult(netRetBean);
    }
}

可以看到,同步请求分支部分的代码和异步请求时差不多,只是父类不一样,还有最后需要将结果进行返回,而不是回调。

到此,框架中同步请求的代码都已经添加完成,可以开始使用了
private void syncGetString() {
    new Thread() {
        @Override
        public void run() {
            String originalString = NetHelper.getStringSync("url");
            System.out.println(originalString);

            NetRetBean netRetBean = NetHelper.getSync("url", new SyncNetStringListener());
            CallbackCode callbackCode = netRetBean.getCallbackCode();
            switch (callbackCode) {
                case CODE_SUCCESS_REQUEST:
                    String string = (String) netRetBean.getServerObject();
                    System.out.println(string);
                    break;
                case CODE_ERROR_HTTP_NOT_200:
                case CODE_ERROR_REQUEST_EXP:
                case CODE_ERROR_SERVER_DATA_ERROR:
                case CODE_ERROR_JSON_EXP:
                case CODE_ERROR_UNKNOWN:
                default:
                    System.out.println(netRetBean.toString());
                    break;
            }
        }
    }.start();
}

getStringSync返回的是最原始的数据,没有经过解析的,他不需要传入监听器参数。
getSync返回的是NetRetBean,传入的监听器类型的不同,NetRetBean中serverObject类型也会不同。当然这里需要开发者自己取出来进行强转。

笔者一开始想把serverObject对象的类型变成泛型,后来发现如果是自定义监听器进行同步请求时,一个泛型对象不够通用,还是得用到serverObjectMap属性才行。

回顾上一篇中的需求,根据url1请求的结果判断是否请求url2,我们可以这样实现
private void syncGetString() {
    new Thread() {
        @Override
        public void run() {
            NetRetBean netRetBean = NetHelper.getSync("url1", new SyncNetStringListener());
            if (netRetBean.isSuccess()) {
                NetHelper.getSync("url2", new SyncNetStringListener());
            }

            try {
                Thread.sleep(60 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }.start();
}

这样的话,代码的执行顺序就很清晰了,返回值的方式也非常符合同步请求的需求,代码看起来简单明了。


我们接着再来使用其它的Listener来完成同步请求。
假设服务端返回的数据是这样的:
{
    "code":"00001",
    "message":"login success",
    "time":"1479807260",
    "data":{
        "id":"123",
        "name":"chenjian"
    }
}

NetUserBean的代码与之前的一样,没有改变
public class NetUserBean extends NetBaseBean {
    private String id;
    private String name;

    @Override
    public void initByJson(JSONObject jsonObject) throws JSONException {
        this.id = jsonObject.optString("id");
        this.name = jsonObject.optString("name");
    }
}

开始使用
private void syncGetBean() {
    new Thread() {
        @Override
        public void run() {
            NetRetBean netRetBean = NetHelper.getSync("url", new SyncNetSingleBeanListener<NetUserBean>());
            CallbackCode callbackCode = netRetBean.getCallbackCode();
            switch (callbackCode) {
                case CODE_SUCCESS_REQUEST:
                    NetUserBean userBean = (NetUserBean) netRetBean.getServerObject();
                    System.out.println(userBean.toString());
                    break;
                default:
                    System.out.println(netRetBean.toString());
                    break;
            }
        }
    }.start();
}

居然报错了
NetRetBean{
mCallbackCode=CODE_ERROR_UNKNOWN, 
mException=java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType,
mServerCode='null', mServerMsg='null', mServerTime='null', mServerData='null', mServerObject=null, mServerObjectMap=null}

再细看异常信息
01-11 13:35:45.470 2432-3428/com.chenjian.net W/System.err: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
01-11 13:35:45.471 2432-3428/com.chenjian.net W/System.err:     at com.chenjian.net.util.NetBaseBeanUtil.getBean(NetBaseBeanUtil.java:41)
01-11 13:35:45.471 2432-3428/com.chenjian.net W/System.err:     at com.chenjian.net.util.NetBaseBeanUtil.parseItem(NetBaseBeanUtil.java:28)
01-11 13:35:45.471 2432-3428/com.chenjian.net W/System.err:     at com.chenjian.net.listener.sync.SyncNetSingleBeanListener.onReceivedRet(SyncNetSingleBeanListener.java:30)
01-11 13:35:45.471 2432-3428/com.chenjian.net W/System.err:     at com.chenjian.net.listener.sync.SyncNetHandleListener.sendSuccess(SyncNetHandleListener.java:46)
01-11 13:35:45.471 2432-3428/com.chenjian.net W/System.err:     at com.chenjian.net.core.sync.SyncNetExcutor.startRequest(SyncNetExcutor.java:83)
01-11 13:35:45.471 2432-3428/com.chenjian.net W/System.err:     at com.chenjian.net.core.sync.SyncNetExcutor.get(SyncNetExcutor.java:64)
01-11 13:35:45.471 2432-3428/com.chenjian.net W/System.err:     at com.chenjian.net.helper.NetHelper.getSync(NetHelper.java:96)
01-11 13:35:45.471 2432-3428/com.chenjian.net W/System.err:     at com.chenjian.net.helper.NetHelper.getSync(NetHelper.java:80)
01-11 13:35:45.471 2432-3428/com.chenjian.net W/System.err:     at com.chenjian.net.demo.activity.GetActivity$5.run(GetActivity.java:189)
01-11 13:35:45.471 2432-3428/com.chenjian.net W/System.err: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
01-11 13:35:45.471 2432-3428/com.chenjian.net W/System.err:     at com.chenjian.net.util.NetBaseBeanUtil.getBean(NetBaseBeanUtil.java:41)
01-11 13:35:45.471 2432-3428/com.chenjian.net W/System.err:     at com.chenjian.net.util.NetBaseBeanUtil.parseItem(NetBaseBeanUtil.java:28)
01-11 13:35:45.471 2432-3428/com.chenjian.net W/System.err:     at com.chenjian.net.listener.sync.SyncNetSingleBeanListener.onReceivedRet(SyncNetSingleBeanListener.java:30)
01-11 13:35:45.471 2432-3428/com.chenjian.net W/System.err:     at com.chenjian.net.listener.sync.SyncNetHandleListener.sendSuccess(SyncNetHandleListener.java:46)
01-11 13:35:45.471 2432-3428/com.chenjian.net W/System.err:     at com.chenjian.net.core.sync.SyncNetExcutor.startRequest(SyncNetExcutor.java:83)
01-11 13:35:45.472 2432-3428/com.chenjian.net W/System.err:     at com.chenjian.net.core.sync.SyncNetExcutor.get(SyncNetExcutor.java:64)
01-11 13:35:45.472 2432-3428/com.chenjian.net W/System.err:     at com.chenjian.net.helper.NetHelper.getSync(NetHelper.java:96)
01-11 13:35:45.472 2432-3428/com.chenjian.net W/System.err:     at com.chenjian.net.helper.NetHelper.getSync(NetHelper.java:80)
01-11 13:35:45.472 2432-3428/com.chenjian.net W/System.err:     at com.chenjian.net.demo.activity.GetActivity$5.run(GetActivity.java:189)

重点在于这两行
java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
at com.chenjian.net.util.NetBaseBeanUtil.getBean(NetBaseBeanUtil.java:41)

我们再看看NetBaseBeanUtil的41行代码
Class<T> entityClass = (Class<T>) ((ParameterizedType) aClass.getGenericSuperclass()).getActualTypeArguments()[tIndex];

很明显的看出来了,aClass.getGenericSuperclass后,是一个Object类型,不能强转为ParameterizedType。
可是之前的SyncNetStringListener为什么没有报错呢?因为SyncNetStringListener并没有用到NetBaseBeanUtil,只是将数据解析为String类型,而不需要使用到NetBaseBeanUtil方法来获取Bean。

那又为什么异步请求时都没问题,而在这个地方就有问题呢?

回忆一下第4篇中提到的java泛型去参数化的概念,我们再来看看NetBaseBeanUtil的代码
public class NetBaseBeanUtil {

    /**
     * @param aClass     带泛型 T 的类,应该传入xxBeanListener监听器或其的子类。他的父类必须是带泛型T的
     * @param tIndex     泛型 T 所在下标
     * @param jsonObject 用来解析的 json
     * @param <T>        泛型 T
     * @return 返回泛型T的实例
     * @throws JSONException
     */
    public static <T extends NetBaseBean> T parseItem(Class aClass, int tIndex, JSONObject jsonObject) throws JSONException {
        T t = getBean(aClass, tIndex);
        t.initByJson(jsonObject);
        return t;
    }

    /**
     * @param aClass 带泛型 T 的类,应该传入xxBeanListener监听器或其的子类。他的父类必须是带泛型T的
     * @param tIndex 泛型 T 所在下标
     * @param <T>    泛型 T
     * @return 返回泛型T的实例
     */
    @SuppressWarnings("unchecked")
    private static <T extends NetBaseBean> T getBean(Class aClass, int tIndex) {
        Class<T> entityClass = (Class<T>) ((ParameterizedType) aClass.getGenericSuperclass()).getActualTypeArguments()[tIndex];
        T entity = null;
        try {
            // 使用newInstance创建实例的类,必须有无参构造方法
            entity = entityClass.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return entity;
    }
}

正如注释所说,这里的aClass的父类必须是带泛型的,而在使用异步请求的时候,因为需要回调,通常的做法是new一个Listener为内部类。而内部类实际上编译器会先定义一个类继承于他,然后再将那个类传入当参数。而同步请求,而直接new一个对象出来,并没有使用他的子类。一起来通过代码对比一下

异步请求我们使用内部类,其实get方法的第二个参数的类型,是NetSingleBeanListener的子类
NetHelper.get("url", new NetSingleBeanListener<NetUserBean>() {
    @Override
    protected void onError(CallbackCode errorCode, NetRetBean netRetBean) {
        
    }

    @Override
    protected void onSuccess(NetUserBean userBean) {
        
    }
});

同步请求时,我们直接生成一个SyncNetStringListener的对象
NetRetBean netRetBean = NetHelper.getSync("url", new SyncNetSingleBeanListener<NetUserBean>());

在两个Listener中,我们在使用NetBaseBeanUtil时,都调用了下面这一行代码
T t = NetBaseBeanUtil.parseItem(getClass(), 0, object);

getClass()非常重要,
在NetSingleBeanListener中,如果是他的子类调用了这个方法,那么返回的是他的子类
在SyncNetSingleBeanListener中,只是本类调用了这个方法,所以返回的是这个类本身

而这个时候,在NetBaseBeanUtil的getBean方法中,需要用到aClass.getGenericSuperclass,对传入的class对象进行操作,
如果传入的aClass是NetSingleBeanListener的子类,那么得到的父类是NetSingleBeanListener,他是带泛型的,可以通过代码取出泛型的类型,再反射
如果传入的aClass是SyncNetSingleBeanListener类,那么得到的父类是SyncNetHandleListener,他是不带泛型的,通过代码取出泛型时就会出错


那既然出现了问题,有办法能解决吗?总不能让同步请求实现不了吧。

一开始,我想到的是,不用getGenericSuperclass的方式取出泛型,而直接在aClass类中取出泛型,但是查阅相关资料后,发现这不可能的。

因为Java泛型去参数化(擦拭法)的原因,只有在 
超类(调用 getGenericSuperclass 方法)
或者成员变量(调用 getGenericType 方法)
或者方法(调用 getGenericParameterTypes 方法)
像这些有方法返回 ParameterizedType 类型的时候才能反射成功

所以使用的时候,必须使用他的子类,而不能直接使用本类。

可以说这非常蛋疼,但你又不得不遵守这样的规则。

那还有其它办法可以解决这个问题吗?显然是有的,只要学习异步请求,用子类就行了。

笔者一开始是直接继承SyncNetSingleBeanListener来实现一个类,假设为MyListener吧,类里面是空的。然后传参的时候,new MyListener(),发现不行的,单步调试时发现aClass.getGenericSuperclass时,居然还是SyncNetHandleListener,没有深入去研究,笔者猜想是编译器直接把这个空的MyListener类给删除掉了。

于是为了让开发者使用框架的时候不混乱,知道要使用哪个Listener,我想到了另一种办法。

还是学异步请求,直接把SyncNetSingleBeanListener定义为抽象类
package com.chenjian.net.listener.sync;

import com.chenjian.net.bean.NetBaseBean;
import com.chenjian.net.bean.NetRetBean;
import com.chenjian.net.util.NetBaseBeanUtil;

import org.json.JSONException;
import org.json.JSONObject;

/**
 * 返回是单个Bean的网络请求Listener
 * <p>
 * 由于去参数化(擦拭法),也只有在
 * 超类(调用 getGenericSuperclass 方法)
 * 或者成员变量(调用 getGenericType 方法)
 * 或者方法(调用 getGenericParameterTypes 方法)
 * 像这些有方法返回 ParameterizedType 类型的时候才能反射成功
 * <p>
 * 所以使用的时候,必须使用他的子类,而不能直接使用本类
 * <p>
 * 作者: ChenJian
 * 时间: 2016.12.15 14:54
 */

abstract public class SyncNetSingleBeanListener<T extends NetBaseBean> extends SyncNetHandleListener {

    @Override
    protected NetRetBean onReceivedRet(NetRetBean netRetBean) throws JSONException {
        JSONObject object = new JSONObject(netRetBean.getServerData());
        T t = NetBaseBeanUtil.parseItem(getClass(), 0, object);
        netRetBean.setServerObject(t);
        return handleResult(netRetBean);
    }
}

这样一来,在使用他的时候,不能直接new,因为抽象类不能生成对象,必须使用他的子类才可以,不然不能编译通过。
一般开发者可以用内部类的方式,其实也是用到了他的子类
private void syncGetBean() {
    new Thread() {
        @Override
        public void run() {
            NetRetBean netRetBean = NetHelper.getSync("url", new SyncNetSingleBeanListener<NetUserBean>() {
            });
            CallbackCode callbackCode = netRetBean.getCallbackCode();
            switch (callbackCode) {
                case CODE_SUCCESS_REQUEST:
                    NetUserBean userBean = (NetUserBean) netRetBean.getServerObject();
                    System.out.println(userBean.toString());
                    break;
                default:
                    System.out.println(netRetBean.toString());
                    break;
            }
        }
    }.start();
}

使用内部类时,只要加一对花括号{}就可以了,因为里面没有未实现的抽象方法,所以花括号里面是空的。

同样,对于SyncNetListBeanListener,我们也定义为抽象类
package com.chenjian.net.listener.sync;

import com.chenjian.net.bean.NetBaseBean;
import com.chenjian.net.bean.NetRetBean;
import com.chenjian.net.util.NetBaseBeanUtil;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

/**
 * 返回是List<Bean>的网络请求Listener
 * <p>
 * 由于去参数化(擦拭法),也只有在
 * 超类(调用 getGenericSuperclass 方法)
 * 或者成员变量(调用 getGenericType 方法)
 * 或者方法(调用 getGenericParameterTypes 方法)
 * 像这些有方法返回 ParameterizedType 类型的时候才能反射成功
 * <p>
 * 所以使用的时候,必须使用他的子类,而不能直接使用本类
 * <p>
 * 作者: ChenJian
 * 时间: 2016.12.15 14:54
 */

abstract public class SyncNetListBeanListener<T extends NetBaseBean> extends SyncNetHandleListener {

    @Override
    protected NetRetBean onReceivedRet(NetRetBean netRetBean) throws JSONException {
        JSONArray array = new JSONArray(netRetBean.getServerData());
        List<T> list = new ArrayList<>();
        for (int i = 0; i < array.length(); i++) {
            JSONObject object = array.getJSONObject(i);
            T t = NetBaseBeanUtil.parseItem(getClass(), 0, object);
            list.add(t);
        }
        netRetBean.setServerObject(list);
        return handleResult(netRetBean);
    }
}

在使用时也很简单
private void syncGetListBean() {
    new Thread() {
        @Override
        public void run() {
            NetRetBean netRetBean = NetHelper.getSync("url", new SyncNetListBeanListener<NetUserBean>() {
            });
            CallbackCode callbackCode = netRetBean.getCallbackCode();
            switch (callbackCode) {
                case CODE_SUCCESS_REQUEST:
                    List<NetUserBean> userBeen = (List<NetUserBean>) netRetBean.getServerObject();
                    for (int i = 0; i < userBeen.size(); i++) {
                        System.out.println(userBeen.get(i).toString());
                    }
                    break;
                default:
                    System.out.println(netRetBean.toString());
                    break;
            }
        }
    }.start();
}


到这里,框架内的同步请求代码已经全部完成。

最后再来回忆一下第6篇的内容,讲的是自定义解析器,其实现方案也只能适合异步请求,那么在同步请求时,我们只要学着SyncNetSingleBeanListener的实现思路,进行一些修改就行
package com.chenjian.net.demo.listener.sync;

import com.chenjian.net.bean.NetBaseBean;
import com.chenjian.net.bean.NetRetBean;
import com.chenjian.net.listener.sync.SyncNetHandleListener;
import com.chenjian.net.util.NetBaseBeanUtil;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 作者: ChenJian
 * 时间: 2016.12.16 13:51
 */

abstract public class SyncNetCustomBeanListener<Page extends NetBaseBean, T extends NetBaseBean> extends SyncNetHandleListener {

    @Override
    protected NetRetBean onReceivedRet(NetRetBean netRetBean) throws JSONException {
        JSONObject jsonObject = new JSONObject(netRetBean.getServerData());

        Page page = NetBaseBeanUtil.parseItem(getClass(), 0, jsonObject);

        List<T> list = new ArrayList<>();
        JSONArray jsonArray = jsonObject.getJSONArray("list");
        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject object = jsonArray.getJSONObject(i);
            T t = NetBaseBeanUtil.parseItem(getClass(), 1, object);
            list.add(t);
        }

        Map<String, Object> map = new HashMap<>();
        map.put("page", page);
        map.put("list", list);

        netRetBean.setServerObjectMap(map);
        return handleResult(netRetBean);
    }
}

使用起来是这样的
private void syncCustom() {
    new Thread() {
        @Override
        public void run() {
            NetRetBean netRetBean = NetHelper.postSync("url", "param", new SyncNetCustomBeanListener<NetPageBean, NetInfoBean>() {
                    });
            CallbackCode callbackCode = netRetBean.getCallbackCode();
            switch (callbackCode) {
                case CODE_SUCCESS_REQUEST:
                    Map<String, Object> map = netRetBean.getServerObjectMap();
                    NetPageBean pageBean = (NetPageBean) map.get("page");
                    List<NetInfoBean> infoBeen = (List<NetInfoBean>) map.get("list");
                    System.out.println(pageBean.toString());
                    for (int i = 0; i < infoBeen.size(); i++) {
                        System.out.println(infoBeen.get(i).toString());
                    }
                    break;
                default:
                    System.out.println(netRetBean.toString());
                    break;
            }
        }
    }.start();
}

使用的时候,因为监听器内部的实现,要使到具体数据的话,要从NetRetBean的serverObjectMap里面取,map的key的值根据SyncNetCustomBeanListener中定义的一样。


总结一下,
当所使用的Listener需要调用NetBaseBeanUtil时,就要实现成抽象类,在使用这类监听器时,要使用他的子类。此处的例子有SyncNetSingleBeanListener,SyncNetListBeanListener,SyncNetCustomBeanListener。
当所使用的Listener不需要调用NetBaseBeanUtil时,就不要实现成抽象类了,在使用这类监听器时,直接创建他的对象。此处的唯一例子就是SyncNetStringListener。

可以说在开发者的角度,使用本框架进行异步请求或者同步请求差别并不大,只是入口从get变成getSync,post变成postSync,监听器也换成了相应的就行了。还要注意的是在自定义监听器时,如果开发者有需要使用到同步请求,也要实现一个同步请求的自定义解析器。如果不需要,就不要实现了。


至此,同步请求的所有内容都已讲解完成。

下一篇将讲解对第三方解析框架的支持
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值