Android数据绑定,MVVM框架,SpringMVC for Android

最近研究怎么让自己的程序节省几行代码。仔细想一想,我们在做客户端类的APP时,最基础,大量重复的场景就是:

1.从服务器请求数据2.解析得到的数据并处理加以封装3.将封装好的数据送到UI线程显示到View上。

那么,不可避免的。一次流程我们需要编写:http数据请求,JSON解析处理,异步处理,Handler,业务异常处理,View显示,如果有集合控件,还得写ViewHolder,Adapter。十几个类,N个方法,数百行不止的代码。枯燥无味,费时费力。

那么怎么办,现在流行rxjava,retrofit等框架,自然是非常方便优雅。但是作为程序猿自然得有自己的想法,于是乎有了下面这个即将介绍给大家的“小玩具”。

首先,思考一下上面所说的一套标准流程,真正不可或缺的只有什么?那就是协议,换句话说就是接口,从数据的角度来说:一是从服务器返回的值的协议(json等数据格式到Model模型的映射),二是你请求服务器的参数协议url,参数,头信息等;除此之外,你需要一个数据到视图的映射关系,以及控制层的接口。从java代码的角度来说,你需要1.接口一个,2.带映射关系的(View到值映射,json到对象映射)Model数据模型类,3.没了。

下面就模拟一下下面所说的场景。我将用我写的小玩具完成一次登陆/注册模拟,带参请求服务器登陆,并返回一段JSON数据,包含jsonobject和jsonarray,并显示到textView和listview上。

1.接口,你需要写一个服务接口,里面有你的业务方法,你只需要在接口的抽象方法上的注解上配置一下,接口实现就交给框架动态代理。

public interface ILogin {

    @HttpSrcMethod(url = "http://www.baidu.com")
    public UserInfoModel login(@Param("name") String name, @Param("pass") String pass, @Header("par3") String par3);

    @HttpSrcMethod(url = "http://www.baidu.com",connMode = HttpConnectMode.Post,runMode = HttpRunMode.Async,filters = TestFilter.class)
    public UserInfoModel regist(@Param("name") String name, @Param("pass") String pass, @Header("par3") String par3);

}

@HttpSrcMethod表示这个方法将被代理为Http请求业务,注解可以指定url,参数,头的参数映射,可以配置同步还是异步请求,亲求方式Post/Get等,还有过滤器,过滤器将在框架解析返回的string之前对返回的字符串进行一些自定义操作,如解密等。


2.完成带映射的数据模型,注解映射JSON/Xml数据元素到Model的关系,注解映射ViewId到Model的关系

@JsonOrm
public class UserInfoModel implements IHandler{

    @BindTextView(R.id.text1)
    @JsonString
    private String name;
    @BindTextView(R.id.text3)
    @JsonString
    private String pass;
    @BindRecycleView(R.id.list)
    @BindObj
    @JsonSet(clazz = ItemModel.class)
    private List<ItemModel> obj;

    @Override
    public void handler() {
        name = name+"handled";
    }
}
<pre name="code" class="java">@ListDataSrc(R.layout.item)
public class ItemModel {
    @BindText(R.id.item_text)
    @JsonString
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}


 
 如果Model实现了IHandler接口,那么框架将会在json/xml解析完成之后,调用handle方法,增加对model的控制力,完成一些较为复杂的数据处理逻辑,这也是这一模式的缺点,控制力低,只适合较为简单的流程逻辑。 
 

这样仅仅通过这一个数据模型类,框架就知道了JSON元素和View之间的关系了。

3.控制层的调用。只需要申明一下你的业务接口,让框架生成代理对象,直接调用即可。

public class MainActivity extends AppCompatActivity implements ICallBack{

    public final static String json = "{\n" +
            "    \"name\": \"gy\",\n" +
            "    \"pass\": \"123\",\n" +
            "    \"obj\": [\n" +
            "        {\n" +
            "            \"name\": \"gy\"\n" +
            "        },\n" +
            "        {\n" +
            "            \"name\": \"gy\"\n" +
            "        },\n" +
            "        {\n" +
            "            \"name\": \"gy\"\n" +
            "        },\n" +
            "        {\n" +
            "            \"name\": \"gy\"\n" +
            "        }\n" +
            "    ]\n" +
            "}";

    private ILogin login;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        login = HttpProxyFactory.With(ILogin.class)
                                .addViewContent("login",this)
                                .addCallBack("login",this)
                                .establish();
        login.login("gy","123","xxxx");
    }

    @Override
    public void onSuccess(Object o) {
        
    }

    @Override
    public void onFailed(Object o) {

    }
}

同时,你可以设置接口中某个业务的回调,以及视图映射所需要的父容器,一般是Activity或者父视图。

关于方便的保持会话,一般就是请求头内包含一个tokenid,sessionid,这里提供了一个方法设置默认的请求头和参数:
//SessionFactory.Session 只是一个请求头和参数的hashmap
        SessionFactory.Session session = new SessionFactory.Session();
        SessionFactory.addSession("default",session);
绑定这个Session也很简单,注解上面指定就好了
public interface ILogin {
    @HttpSrcMethod(url = "",session = "beforelogin")
    public User login(@Param("name")String name,@Param("passwd")String passwd);
}


4.最后,由于框架在解析Model和接口的时候使用的巨量的反射操作,几乎占用了主线程50-100ms的时间。为了优化性能,异步的预加载是必须的,我们在Application中,预先解析好接口和Model的数据结构存在缓存中。大大优化了性能,其实反射的主要耗时在与方法,接口等类型元素的查找获取,而invoke其实对性能的影响可以忽略不计。
public class MyApplication extends Application{
    @Override
    public void onCreate() {
        super.onCreate();
        S.init(this);
        MvvmCacheControl.preLoad(new Class[]{ILogin.class});
    }
}
附上结果


好了,忙里偷闲水了一篇,以上只是对这个小玩意的使用介绍,这个还属于demo级,有很多功能还没有实现,代码也不够健壮。具体的实现分析就放在下一篇好了,敬请期待。下面附上源码地址,整合在我的小框架里了,Android Studio直接导入工程即可 GitHub



猜你喜欢

转载自blog.csdn.net/ganyao939543405/article/details/52389852