Silk,一个基于java bean的轻量级响应式框架

xip448483 9年前
   <h2><strong>Silk</strong></h2>    <p>一个基于java bean的响应式框架</p>    <h3><strong>Why we need this?</strong></h3>    <p>假设我们有这么一个需求:</p>    <p>我们登陆成功之后通过服务器拿到一个useraccount对象,useraccount对象长这个样子</p>    <pre>  <code class="language-java">public class UserAccount{    private String userName;//姓名    private int age;//年龄    private String userImage;//头像      public void setUserName(String userName){      this.userName = userName;    }      public String getUserName(){      return userName;    }      //后略......  }</code></pre>    <p>我们会在界面上展示登陆用户的姓名,头像等等:</p>    <pre>  <code class="language-java">UserAccount useraccount = getUserAccount();//获取到了useraccount对象  TextView tvName = findViewById(R.id.tv_name);  tvName.setText(useraccount.getUserName());</code></pre>    <p>OK,接下来如果我们需要修改用户的姓名,那么以往我们是这样的:</p>    <pre>  <code class="language-java">useraccount.setUserName("mike");  //其他的工作  tvName.setText(useraccount.getUserName());  //其他的展示</code></pre>    <p>这里面,我们一般是给对象set了某个值之后,再更新UI。</p>    <h3><strong>Now,We change</strong></h3>    <p>使用silk之后,现在我们的useraccount定义是这样的:(就多了一个注解而已)</p>    <pre>  <code class="language-java">@RxBean  public class UserAccount{    private String userName;//姓名    private int age;//年龄    private String userImage;//头像      public void setUserName(String userName){      this.userName = userName;    }      public String getUserName(){      return userName;    }      //后略......  }</code></pre>    <p>我们接下来这样展示里面的数据:</p>    <pre>  <code class="language-java">TextView tvName = findViewById(R.id.tv_name);  SilkBrite<UserAccount> brite = SilkBrite.create();//初始化了一个brite  UserAccount useraccount = brite.asSilkBean(getUserAccount());//获取useraccount对象,其实这是一个“换了包”的对象  brite.asModeObservable()      .subscribeOn(Schedulers.io())      .observeOn(AndroidSchedulers.mainThread())      .subscribe(new Action1<UserAccount>() {                      @Override                      public void call(UserAccount info) {                          tvName.setText(useraccount.getUserName());                      }                  });</code></pre>    <p>然后我们要修改用户姓名了!</p>    <pre>  <code class="language-java">//你只需要做下面这件事,UI上面就会同步  useraccount.setUserName("mike");</code></pre>    <p>所以,用了silk,我们就不需要每次修改了bean之后还要去同步UI。</p>    <h2><strong>引用</strong></h2>    <ul>     <li>gradle,在你的app的build.gradle文件中引入依赖 <pre>  <code class="language-java">dependencies {    ...    compile 'com.github.landscapeside:SilkLib:1.0'    apt 'com.github.landscapeside:SilkComplier:0.1'    ...  }</code></pre> 然后在你的app的build.gradle中应用apt插件: <pre>  <code class="language-java">apply plugin: 'com.neenbedankt.android-apt'</code></pre> project的build.gradle中申明: <pre>  <code class="language-java">dependencies {        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'    }</code></pre> 用的是jitpack仓库,所以需要在project的build.gradle中注明 <pre>  <code class="language-java">allprojects {    repositories {        jcenter()        maven { url "https://jitpack.io" }    }  }</code></pre> </li>    </ul>    <h2><strong>用法</strong></h2>    <ul>     <li>如上所说,在你需要silk功能的java bean类上使用RxBean注解,然后重新构建一下项目</li>     <li>然后要新建一个SilkBrite出来 SilkBrite<UserAccount> brite = SilkBrite.create(); ,注意,目前来说,一个brite就对应处理一个bean对象</li>     <li>接下来需要将原有的bean对象设置一个代理 UserAccount useraccount = brite.asSilkBean(getUserAccount());</li>     <li>上一步生成的代理对象才能真正嵌入到Silk响应式框架之中,通过bean的setter即可触发相应</li>     <li>我们需要监听到事件源发出的消息并作出反应 <pre>  <code class="language-java">brite.asModeObservable()    .subscribeOn(Schedulers.io())    .observeOn(AndroidSchedulers.mainThread())    .subscribe(new Action1<UserAccount>() {                    @Override                    public void call(UserAccount info) {                        tvName.setText(useraccount.getUserName());                    }                });</code></pre> </li>     <li> <p>当然,还可以嵌套使用,比如一个Parent对象有2个Child,不管是修改Parent的属性或者是child属性,我们都希望能得到通知,则两个类都标记上RxBean注解即可</p> <p>```java</p> <p>@RxBean</p> <p>public class Parent{</p> <p>private String userName;//姓名</p> <p>private int age;//年龄</p> <p>private String userImage;//头像</p> <p>private Child child1;</p> <p>private Child child2;</p> <p>public void setUserName(String userName){</p> <p>this.userName = userName;</p> <p>}</p> <p>public String getUserName(){</p> <p>return userName;</p> <p>}</p> <p>//后略......</p> <p>}</p> </li>    </ul>    <p>@RxBean</p>    <p>public class Child{</p>    <p>private String userName;//姓名</p>    <p>private int age;//年龄</p>    <p>//......</p>    <p>}</p>    <pre>  <code class="language-java">* 有时候我们有这样的需求,显示UserAccount的nick的时候希望能加上如果为空的默认显示  ```java  brite.asNodeObservable("nick")          .subscribeOn(Schedulers.io())          .observeOn(AndroidSchedulers.mainThread())          .map(o1 -> {              String name = String.valueOf(o1);              if (TextUtils.isEmpty(name)) {                  return "unknown user";              }              return name;          })          .subscribe(new Action1<String>() {                  @Override                  public void call(String name) {                      tvName.setText(name);                  }              });</code></pre>    <ul>     <li>如果是要加上child的默认显示 <pre>  <code class="language-java">brite.asNodeObservable("child1::userName")        .subscribeOn(Schedulers.io())        .observeOn(AndroidSchedulers.mainThread())        .map(o1 -> {            String name = String.valueOf(o1);            if (TextUtils.isEmpty(name)) {                return "unknown user";            }            return name;        })        .subscribe(new Action1<String>() {                @Override                public void call(String name) {                    tvName.setText(name);                }            });</code></pre> </li>    </ul>    <h2><strong>限制</strong></h2>    <ul>     <li> <p>首先,一个brite就是用来处理一个bean对象,所以并不太适合列表类的应用,当然后续会考虑改进</p> </li>     <li> <p>而且就如Silk的开发目的一样,它就只是为了解决基于bean的响应式编程。</p> </li>    </ul>    <p> </p>    <p> </p>    <p>来自:http://www.jianshu.com/p/f4be589eb775</p>    <p> </p>