MVVM+DataBinding+RxJava+Retofit实现一个简单的新闻demo

MVVM+DataBinding+RxJava+Retofit实现一个简单的新闻demo

引入databinding

 dataBinding {
            enabled true
        }

引入相关依赖

 //ViewModel与LiveData
    implementation "android.arch.lifecycle:extensions:1.1.1"

    // 依赖RxAndroid 2X 的依赖库
    // 增加RxJava 2X 的依赖库
    implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
    implementation 'io.reactivex.rxjava2:rxjava:2.2.9'

    // Retrofit库
    implementation 'com.squareup.retrofit2:retrofit:2.0.2'

    // Okhttp库
    implementation 'com.squareup.okhttp3:okhttp:3.1.2'

    //Gson依赖
    implementation 'com.squareup.retrofit2:converter-gson:2.0.2'

    //图片加载
    implementation 'com.github.bumptech.glide:glide:4.11.0'

加入网络请求权限

 <uses-permission android:name="android.permission.INTERNET"/>

代码

MainActivity

public class MainActivity extends AppCompatActivity {

    private ActivityMainBinding binding;

    private MainViewModel viewModel;

    private NewsRecyclerAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
        init();
        initData();
    }

    //调整每个item之间的距离
    class SpaceItemDecoration extends RecyclerView.ItemDecoration {
        int mSpace;

        @Override
        public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
            super.getItemOffsets(outRect, view, parent, state);
            outRect.bottom = mSpace;
            if (parent.getChildAdapterPosition(view) == 0) {
                outRect.top = mSpace;
            }
        }

        public SpaceItemDecoration(int space) {
            this.mSpace = space;
        }
    }

    private void init() {
        //初始化ViewModel
        viewModel = ViewModelProviders.of(this).get(MainViewModel.class);
        viewModel.request();
        Log.i("sjh","我是你爸爸");
    }

    private void initData() {
        binding.setModel(viewModel);
        //数据请求
        viewModel.getNewsList().observe(this, new Observer<List<News.NewslistBean>>() {
            @Override
            public void onChanged(List<News.NewslistBean> newslistBeans) {
                LinearLayoutManager linearLayoutManager = new LinearLayoutManager(binding.getRoot().getContext());
                binding.recyclerView.setLayoutManager(linearLayoutManager);
                adapter = new NewsRecyclerAdapter(binding.getRoot().getContext());
                binding.recyclerView.addItemDecoration(new SpaceItemDecoration(5));
                binding.recyclerView.setAdapter(adapter);
                adapter.addAll(newslistBeans);
            }
        });
    }
}

ViewModel类,与view层交互,请求网络获取数据

public class MainViewModel extends ViewModel {

    //当数据请求成功回调
    protected MutableLiveData<List<News.NewslistBean>> newsList=new MutableLiveData<>();

    public void request() {

        //RxJava切换线程
        Observable.create(new ObservableOnSubscribe<News>() {
            @Override
            public void subscribe(@NonNull final ObservableEmitter<News> emitter) throws Exception {
                // Retrofit进行网络请求
                Retrofit retrofit = new Retrofit.Builder()
                        .baseUrl("http://api.tianapi.com/")
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();

                GetRequest_Interface request = retrofit.create(GetRequest_Interface.class);

                Call<News> call = request.getCall();

                call.enqueue(new Callback<News>() {
                    @Override
                    public void onResponse(Call<News> call, Response<News> response) {
                        News news = response.body();
                        emitter.onNext(news); //将news通过发射器发送给Observer
                    }

                    @Override
                    public void onFailure(Call<News> call, Throwable t) {
                        System.out.println("连接失败");
                        System.out.println(t.getMessage());
                    }
                });
            }
        })
        .subscribeOn(Schedulers.io())  // 为上面代码分配io线程
        .observeOn(AndroidSchedulers.mainThread())   // 为下面代码分配主线程
        .subscribe(new Observer<News>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {

            }

            @Override
            public void onNext(@NonNull News news) {
                if (news != null) {
                    newsList.postValue(news.getNewslist());
                }
            }

            @Override
            public void one rror(@NonNull Throwable e) {

            }

            @Override
            public void onComplete() {

            }
        });
    }

    public MutableLiveData<List<News.NewslistBean>> getNewsList() {
        return newsList;
    }
}

RecyclerView的适配器类

public class NewsRecyclerAdapter extends RecyclerView.Adapter<BindingViewHolder> {
    private LayoutInflater layoutInflater;
    private OnItemClickListener mListener; //item的点击监听器
    private List<News.NewslistBean> list;

    public interface OnItemClickListener {
        void onItemClickListener(News.NewslistBean news);
    }

    public NewsRecyclerAdapter(Context context) {
        this.layoutInflater = LayoutInflater.from(context);
        this.list = new ArrayList<>();
    }

    @NonNull
    @Override
    public BindingViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        ViewDataBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.item_news_fragment,parent,false);
        return new BindingViewHolder(binding);
    }

    @Override
    public void onBindViewHolder(@NonNull BindingViewHolder holder, int position) {
        final News.NewslistBean news = list.get(position);
        ViewDataBinding binding = holder.getBinding();
        binding.setVariable(BR.news,news);
        binding.executePendingBindings();

        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mListener != null) {
                    mListener.onItemClickListener(news);
                }
            }
        });
    }

    @Override
    public int getItemCount() {
        return list.size();
    }

    public void setOnItemClickListener(OnItemClickListener listener) {
        this.mListener = listener;
    }

    public void addAll(List<News.NewslistBean> news) {
        list.addAll(news);
    }
}

加载网络图片双向绑定ImageView的工具类

public class DataBindingUtil {
    @BindingAdapter("BaseUrl")
    public static void loadImage(ImageView view, String url){
        Glide.with(view.getContext()).load(url).into(view);
    }
}

网络请求接口

public interface GetRequest_Interface {
    @GET("social/index?key=d44ec13840090282a1af867dec47bbbd&num=50")
    Call<News> getCall();
    // 注解里传入 网络请求 的部分URL地址
    // Retrofit把网络请求的URL分成了两部分:一部分放在Retrofit对象里,另一部分放在网络请求接口里
    // 如果接口里的url是一个完整的网址,那么放在Retrofit对象里的URL可以忽略
    // getCall()是接受网络请求数据的方法
}

顶层BindingViewHolder类

public class BindingViewHolder<T extends ViewDataBinding> extends RecyclerView.ViewHolder {
    private T mBinding;
    public BindingViewHolder(@NonNull T binding) {
        super(binding.getRoot());
        mBinding = binding;
    }

    public T getBinding() {
        return mBinding;
    }
}

新闻实体类

/**
 * 新闻实体类
 * */
public class News extends BaseObservable {


    /**
     * code : 200
     * msg : success
     * newslist : [{"id":"2f5ef5351c8139baecf39b97133db3d3","ctime":"2021-03-13 09:45","title":"这段东北女法官庭审视频火出圈了 也就看了100来遍","description":"","source":"中华社会","picUrl":"https://img0.utuku.imgcdc.com/300x200/news/20210313/9a6cc7ae-37f5-4bba-8e0e-fcd23e1eac54.jpg","url":"https://news.china.com/social/1007/20210313/39375399.html"}]
     */

    private Integer code;
    private String msg;
    private List<NewslistBean> newslist;

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public List<NewslistBean> getNewslist() {
        return newslist;
    }

    public void setNewslist(List<NewslistBean> newslist) {
        this.newslist = newslist;
    }

    public class NewslistBean extends BaseObservable{
        /**
         * id : 2f5ef5351c8139baecf39b97133db3d3
         * ctime : 2021-03-13 09:45
         * title : 这段东北女法官庭审视频火出圈了 也就看了100来遍
         * description :
         * source : 中华社会
         * picUrl : https://img0.utuku.imgcdc.com/300x200/news/20210313/9a6cc7ae-37f5-4bba-8e0e-fcd23e1eac54.jpg
         * url : https://news.china.com/social/1007/20210313/39375399.html
         */

        private String id;
        private String ctime;
        private String title;
        private String description;
        private String source;
        private String picUrl;
        private String url;

        @Bindable
        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
            notifyPropertyChanged(BR.id);
        }

        @Bindable
        public String getCtime() {
            return ctime;
        }

        public void setCtime(String ctime) {
            this.ctime = ctime;
            notifyPropertyChanged(BR.ctime);
        }

        @Bindable
        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
            notifyPropertyChanged(BR.title);
        }

        @Bindable
        public String getDescription() {
            return description;
        }

        public void setDescription(String description) {
            this.description = description;
            notifyPropertyChanged(BR.description);
        }

        @Bindable
        public String getSource() {
            return source;
        }

        public void setSource(String source) {
            this.source = source;
            notifyPropertyChanged(BR.source);
        }

        @Bindable
        public String getPicUrl() {
            return picUrl;
        }

        public void setPicUrl(String picUrl) {
            this.picUrl = picUrl;
            notifyPropertyChanged(BR.picUrl);
        }

        @Bindable
        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
            notifyPropertyChanged(BR.url);
        }
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="model"
            type="com.example.retrofit.MainViewModel" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

    </LinearLayout>
</layout>

item_news_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <variable
            name="news"
            type="com.example.retrofit.News.NewslistBean" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:padding="12dp"
        android:background="#FFF">

        <ImageView
            android:id="@+id/imageView13"
            android:layout_width="70dp"
            android:layout_height="70dp"
            android:scaleType="centerCrop"
            app:BaseUrl="@{news.picUrl}"/>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginLeft="8dp"
            android:orientation="vertical">

            <TextView
                android:id="@+id/textView13"
                android:layout_marginTop="10dp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:singleLine="true"
                android:text="@{news.title}"
                android:textSize="16sp"
                android:textStyle="bold"
                android:textColor="#000"/>

            <TextView
                android:id="@+id/textView15"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="30dp"
                android:maxLines="2"
                android:text="@{news.ctime}"
                android:textSize="12sp"/>

        </LinearLayout>
    </LinearLayout>
</layout>

运行效果

MVVM+DataBinding+RxJava+Retofit实现一个简单的新闻demo

上一篇:爬虫快速入门(二):动态页面抓取


下一篇:jsp中怎么重写url