美文网首页Android开发Android知识程序员
记录data binding和CleanArchitecture

记录data binding和CleanArchitecture

作者: 我想要有你在的未来 | 来源:发表于2017-05-02 15:49 被阅读403次

    最近在做一个公司内部的app,框架方面使用了CleanArchitecture,因为本身app的业务逻辑不是很复杂,所以在使用的时候我没有写presenter这一层,只有当页面逻辑比较复杂的时候还会去写presenter层,主要还是懒得去写那么多接口。
    1:databinding的使用,这里就不详细的去介绍,可以去看databinding官网。只说几个项目中比较常用的,
    (1)就是textview的使用

    <TextView
                android:layout_width="60dp"
                android:layout_height="wrap_content"
                android:layout_marginLeft="20dp"
                android:text="@{item.startedStatus}"
                android:textColor="@color/dicuss_content_text_color"
                tools:text="启动状态"/>
    
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:text="@{@string/monthperformance(totalContributionCount, totalInGroupCount)}"
        android:textColor="@color/white"
        android:textSize="13sp"
        tools:text="总计:贡献额:3928191.21 元   入组数:102910 例"/>
    

    使用多个的的时候在strings里面定义的记得要写上%1和%2要不然会报错的。

    <string name="monthperformance">总计:贡献额:%1$d 元   入组数:%2$d 例</string>
    

    (2)view的VISIBLE和GONE

      <data>
            <import type="android.view.View"/>
            <variable
                name="item"
                type="com.xxx.xxxx.model.QuestionModel"/>
            <variable
                name="presenter"
                type="com.xxx.xxx.view.business.common.DetailActivity.Presenter"/>
        </data>
    
    <ImageView
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:onClick="@{() -> presenter.onTopClick(item)}"
              android:src="@{item.topStatus ? @drawable/ic_had_up : @drawable/ic_up}"
              android:visibility="@{item.myQuestion ? View.VISIBLE : View.GONE}"
              tools:src="@drawable/ic_had_up"/>
    

    这部分很好的说明了点击事件的使用和view的显示和隐藏,也可以根据状态来选择不同的src。
    (3)onLongClick事件

      <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal"
                android:onClick="@{() -> presenter.onItemClick(item)}"
                android:onLongClick="@{() -> presenter.onItemLongClick(item)}"
                android:orientation="vertical"
                android:paddingRight="25dp"
                android:visibility="@{item.showProgress ? View.INVISIBLE : View.VISIBLE}">
     ....省略代码
    

    记得在定义方法的时候记得要有个boolean类型的返回,当时没有注意到导致了databinding生成不了,后来看了官网才发现,怪自己啊。。。

    public boolean onItemLongClick(FileModel model) {
      
        return true;
    }
    

    (4)在RecyclerView方面的使用,使用了databindingAdapter,代码非常的简单,使用起来也非常的方便好比

     mAdapter = new MultiTypeAdapter(this);
            mAdapter.addViewTypeToLayoutMap(PROJECT_VIEW_TYPE, R.layout.item_discuss_project);
            mAdapter.addViewTypeToLayoutMap(STUDY_VIEW_TYPE, R.layout.item_discuss_study);
            mAdapter.addViewTypeToLayoutMap(EXPERIENCE_VIEW_TYPE, R.layout.item_discuss_experience);
            mAdapter.setPresenter(new Presenter());
            getRecyclerViewWithFooter().setAdapter(mAdapter);
            getRecyclerViewWithFooter().setVerticalLinearLayout();
    

    这是我RecyclerView多个布局的定义,在xml中使用

     <data>
    
            <import type="android.view.View"/>
    
            <variable
                name="item"
                type="com.xxx.xxx.model.CommentModel"/>
    
            <variable
                name="presenter"
                type="com.xxx.xxx.listener.CommentPresenter"/>
        </data>
    

    就是数据的name为item和事件的name为presenter。更多的使用可以自己去看github上的介绍。
    (5)图片访问方面,因为这个app图片的使用上还是蛮多的,所以选择了Fresco(也看中它能在xml中写一些配置),不太好的地方就是包的体积大了些,但是还是能接受的。

    <com.xxx.xxx.view.widget.MyDraweeView
                    android:layout_width="@dimen/user_avater_w"
                    android:layout_height="@dimen/user_avater_w"
                    app:failureImage="@drawable/ic_avatar"
                    app:placeholderImage="@drawable/ic_avatar"
                    app:roundAsCircle="true"
                    app:url="@{item.avatar}"/>
    

    这里的MyDraweeView是继承SimpleDraweeView因为fresco是不支持自适应的,所以在这里你可以自己设置view的LayoutParams来达到目的。
    2:CleanArchitecture框架的使用。github地址
    (1)api和repository,我把各个模块的api都分开定义,这样在分模块开发的时候,可以各自定义api

    api.png
    (2)dagger,在定义module的时候我采用的是new的方式,而不是使用在构造函数上加@Inject,因为采用new的方式能达到局部单例的效果,
    @Module
    public class ProjectModule {
    
        public ProjectModule() {
        }
    
        @Provides
        @PerActivity
        ProjectSearchUseCase provideProjectSearchUseCase(ProjectRepository projectRepository,
                                                         ThreadExecutor threadExecutor,
                                                         PostExecutionThread postExecutionThread) {
            return new ProjectSearchUseCase(projectRepository, threadExecutor, postExecutionThread);
        }
    
    }
    
    this.provideProjectHistoryUseCaseeProvider =
            DoubleCheck.provider(
                ProjectModule_ProvideProjectHistoryUseCaseeFactory.create(
                    builder.projectModule,
                    userRepositoryProvider,
                    threadExecutorProvider,
                    postExecutionThreadProvider));
    

    这里的doublecheck就是起到这里这个效果,dagger中的单例也是如此,而不是你加上@Singleton就是单例了,是要在Application中才能达到单例的效果。这里就不展开了。
    (3)component也是采用的分模块定义,在fragment和activity使用上我也是采用和github上一样的方法在activity上提供component,activity实现HasComponent接口,在fragment里面

     protected <C> C getComponent(Class<C> componentType) {
            return componentType.cast(((HasComponent<C>) getActivity()).getComponent());
        }
    

    就能获取到activity的component了。
    (4)CleanArchitecture中的各种DataMapper,之前不是很理解这个是干什么用的,github上在data层和presentation两层同时使用了。后来在实践的时候发现presentation这层的转化还是非常有必要的。当后台接口返回的数据格式不是你想要的时候,(后台还懒得去帮你改)你可以定义一层转换,还是就是viewmodel中还包含了一些接口返回没有的字段,好比一个view是否显示


    datamapper.png

    当后台返回的数据类型不是你想要的好比boolean类型返回的是string的‘0’和‘1’,还有就是null的判断,尽量的让view获取到的数据不是空对象。
    (5)缓存方面,本身app就没有多大的缓存,只是记录一下搜索记录,没有引入什么第三方的数据库之类的,只是很简单的把搜索记录存入一个文件中

      if (!TextUtils.isEmpty(content)) {
                final File file = this.buildFile(fileName);
                List<String> history = getHistoryList(fileName, false);
                if (history.contains(content)) {
                    history.remove(content);
                }
                history.add(content);
                final String jsonString = mGson.toJson(history).toString();
                this.executeAsynchronously(new CacheWriter(mFileManager, file, jsonString));
            }
    

    在每次搜索的时候保存搜索记录

     @Override
        public Observable<ProjectEntity> getSearchData(ProjectSearch search, boolean isSave) {
            return mProjectApi.getListAndSearch(search)
                    .doOnNext(entity -> {
                        if (isSave) {
                            ProjectDataRepository.this.mCacheImp.putProjectSearchHistory(search.getKey_Words());
                        }
                    })
                    .compose(RepositoryUtils.handleResult());
        }
    

    3:记录一次RecyclerView嵌套webview的问题,一开始我直接在layout布局里面是这样写的,发现页面显示不全(原因未找到。。。要是有人知道原因欢迎告知)。

     <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/white"
            android:orientation="vertical">
    
            <WebView
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                app:weburl="@{item.studyContent}"/>
    
            <include layout="@layout/layout_detail_discuss_header"/>
    
        </LinearLayout>
    
    

    解决方法就是自定义一个view继承LinearLayout,采用动态生成webview这样就能显示全了。

      setOrientation(VERTICAL);
            mWeb = new WebView(getContext().getApplicationContext(), null);
            WebSettings setting = mWeb.getSettings();
            setting.setJavaScriptEnabled(true);
            setting.setBuiltInZoomControls(true);
            setting.setUseWideViewPort(true);
            setting.setLoadWithOverviewMode(true);
            setting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            addView(mWeb, params);
            LinearLayout tagViewsLayout = (LinearLayout) LayoutInflater.from(getContext()).inflate(R.layout.layout_detail_discuss_header, null);
            addView(tagViewsLayout);
    

    使用databinding的时候确实让我感受到了比平时写的要快一些,再也不是写id了也不用设置值了,写起来还是比较爽的,期间也遇到了一些问题,就是使用databinding和dagger一起使用的时候报错,有时候定位不是很准确,但是只要认真看看还是能找得到错误之处的,可能是因为我还是能力还不够的问题。通过这次的实践,让我更加深刻的理解了CleanArchitecture这个框架,也体会到了一些好的框架带来的好处。

    相关文章

      网友评论

        本文标题:记录data binding和CleanArchitecture

        本文链接:https://www.haomeiwen.com/subject/rrlctxtx.html