在gradle.properties中添加:android.enableAapt2 = false
添加网络权限:
添加依赖:
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
compile 'com.truizlop.sectionedrecyclerview:library:1.2.0'
implementation 'com.android.support:recyclerview-v7:26.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
compile "io.reactivex.rxjava2:rxjava:2.1.5"
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'com.github.bumptech.glide:glide:3.8.0'
布局文件.xml
activity_main.xml
xml version="1.0" encoding="utf-8"?> <RelativeLayout 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" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.day09_zuoye.MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent"/> RelativeLayout>
item_movie.xml
xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:orientation="vertical" android:gravity="center_horizontal" android:padding="16dp" android:layout_height="wrap_content"> <ImageView android:id="@+id/pic_iv" android:src="@mipmap/ic_launcher" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:text="asdasdasdasdasd" android:id="@+id/title_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" /> LinearLayout>
item_movie_footer.xml
xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp"> <TextView android:id="@+id/footer_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:text="查看更多" android:textColor="#666666" /> RelativeLayout>
item_movie_header.xml
xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp"> <TextView android:id="@+id/header_tv" android:textSize="28sp" android:textColor="#666666" android:layout_width="wrap_content" android:layout_height="wrap_content" /> RelativeLayout>
MainActivity.java
package com.example.day09_zuoye; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import com.example.day09_zuoye.adapter.MovieAdapter; import com.example.day09_zuoye.bean.MovieBean; import com.example.day09_zuoye.httpservice.MovieHttpService; import java.util.List; import io.reactivex.functions.Consumer; import io.reactivex.functions.Function; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; import retrofit2.Retrofit; import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; import retrofit2.converter.gson.GsonConverterFactory; public class MainActivity extends AppCompatActivity { protected RecyclerView mRecyclerView; private Retrofit mRetrofit; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setContentView(R.layout.activity_main); initView(); loadData(); } private void loadData() { mRetrofit = new Retrofit.Builder() .baseUrl("http://api.shigeten.net/") .addConverterFactory( GsonConverterFactory.create()) .addCallAdapterFactory( RxJava2CallAdapterFactory.create()) .build(); Observableobservable = mRetrofit.create(MovieHttpService.class) .getObservable(); observable.subscribeOn( Schedulers.io()) .map(new Function >() { @Override public List apply(MovieBean movieBean) throws Exception { return movieBean.getResult(); } }) .observeOn( AndroidSchedulers.mainThread()) .subscribe(new Consumer >() { @Override public void accept(List
resultBeans) throws Exception { MovieAdapter adapter = new MovieAdapter(MainActivity.this, resultBeans); mRecyclerView.setAdapter(adapter); } }); } private void initView() { mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); // 设置列表布局管理者 LinearLayoutManager layoutManager = new LinearLayoutManager(this); mRecyclerView.setLayoutManager(layoutManager); } }
adapter文件夹下MovieAdapter.java
package com.example.day09_zuoye.adapter; import android.content.Context; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.example.day09_zuoye.R; import com.example.day09_zuoye.bean.MovieBean; import com.example.day09_zuoye.viewholder.MovieFooterViewHolder; import com.example.day09_zuoye.viewholder.MovieHeaderViewHolder; import com.example.day09_zuoye.viewholder.MovieViewHolder; import com.truizlop.sectionedrecyclerview.SectionedRecyclerViewAdapter; import java.util.ArrayList; import java.util.List; public class MovieAdapter extends SectionedRecyclerViewAdapter{ private Context mContext; // Activity传进来的原始数据集合 private List mDatas; // 每段中item数据的集合 private List mResultList; // 段落集合 private List > mSectionList; // 每段中item的数量 private int mItemCountForSection = 2; // 标题的集合 private List
mTitleList; // 段数 private int mSectionCount; public MovieAdapter(Context context, List datas) { mContext = context; mDatas = datas; initTitle(); changeData(mDatas); } // 对原始数据变化:第xxx段中的第xxx个数据 private void changeData(List datas) { mSectionList = new ArrayList<>(); for (int i = 0; i < datas.size(); i++) { if (i % 2 == 0) { mResultList = new ArrayList<>(); mResultList.add(datas.get(i)); // item数量的奇偶判断 if (datas.size() / 2 == 0) { mResultList.add(datas.get(i + 1)); } else { if (i < datas.size() - 1) { mResultList.add(datas.get(i + 1)); } } mSectionList.add(mResultList); } } } // 初始化全部标题 private void initTitle() { mSectionCount = mDatas.size() / mItemCountForSection + mDatas.size() % mItemCountForSection; mTitleList = new ArrayList<>(); // 标题数量跟随段落数量而确定 for (int i = 0; i < mSectionCount; i++) { mTitleList.add("标题:" + i); } } // 获取大item(段落)的数量 @Override protected int getSectionCount() { return mDatas.size() / mItemCountForSection + mDatas.size() % mItemCountForSection; } // 每个段落中item数据的数量 @Override protected int getItemCountForSection(int section) { int count; if (section == mSectionCount - 1) {// 最后一段 count = (mDatas.size() / 2 == 0) ? 2 : 1; } else { count = 2; } return count; } // 控制段落中是否展示尾视图 @Override protected boolean hasFooterInSection(int section) { return true; } // 创建头视图ViewHolder @Override protected MovieHeaderViewHolder onCreateSectionHeaderViewHolder(ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(mContext) .inflate( R.layout.item_movie_header, parent, false); return new MovieHeaderViewHolder(itemView); } // 创建尾视图ViewHolder @Override protected MovieFooterViewHolder onCreateSectionFooterViewHolder(ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(mContext) .inflate(R.layout.item_movie_footer, parent, false); return new MovieFooterViewHolder(itemView); } // 创建项数据item视图ViewHolder @Override protected MovieViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(mContext) .inflate(R.layout.item_movie, parent, false); return new MovieViewHolder(itemView); } // 头视图数据的绑定(UI控件展示数据) @Override protected void onBindSectionHeaderViewHolder(MovieHeaderViewHolder holder, int section) { String title = mTitleList.get(section); holder.bind(title); } // 尾视图数据的绑定(UI控件展示数据) @Override protected void onBindSectionFooterViewHolder(MovieFooterViewHolder holder, int section) { } // 详细数据item视图数据的绑定(UI控件展示数据) @Override protected void onBindItemViewHolder(MovieViewHolder holder, int section, int position) { // 获取第section段中的第position个数据 Log.d("1510", "section: " + section + ", position : " + position); MovieBean.ResultBean result = mSectionList.get(section).get(position); holder.bind(result); } }
bean文件夹下MovieBean.java
package com.example.day09_zuoye.bean; import java.util.List; public class MovieBean { /** * result : [{"id":100483,"type":1,"publishtime":636505344000000000,"title":"《离开的女人》计划好退场却全神贯注看完四小时","summary":"这是一部接近伟大的电影,虽然结尾有些拖沓。另外电影可以剪辑到3个小时,但这部电影无论如何不能剪到3个小时以下。\r\n\r\n女主人公被富人陷害,在监狱里关了20年,被宣布无罪释放之后,她回家把地卖了,卖地的钱用来施行复仇,这本身就说明她的社会经济地位并不算太低。在反复踩点观察下手时机的过程中,她接触到菲律宾社会最底层的小百姓,生活对他们来说每天都是地狱。女主人公因此放弃复仇计划,回城市去找她失散的儿子。\r\n\r\n电影中Hollanda 为了报答女主人公善良,趁女主人公喝醉之际,偷了她的枪去杀她的仇人。电影里Hollanda 刺杀成功。但我觉得应该拍成刺杀不成功,反而被富人的保镖打死。这样的结局更自然,也更显悲剧。\r\n\r\n导演Lav Diaz 对菲律宾社会的底层小人物充满了同情,他早年做新闻记者的经历对他拍摄电影有很大的帮助。","image":"images/342742C2CD5CC6FD60D142038C88D548.png"},{"id":100482,"type":1,"publishtime":636504480000000000,"title":"《嘉年华》必须克制的态度","summary":"电影聚焦着赤裸裸的痛点,却又无处呐喊,无处宣泄,或许这就是现实。2017媲美《相爱相亲》的华语佳作,就像耿乐说的,这样的电影能公映已经很欣慰了\u2026\r\n\r\n少女性侵案,同情很容易,手撕罪犯也不难,但除此以外呢?片中两位母亲的做法,恐怕正好解释了悲剧不是随机并无意发生的。相比不可饶恕的恶,不自知其过的罪更是笼罩在中国社会的乌云,与当下时愈发强大的男权功守道不谋而合。精准的镜头,几乎没有废戏,视点交还予女孩的处理方法真心很棒。","image":"images/080C6F7487D19E0EB52EA7FFD5906F63.png"},{"id":100481,"type":1,"publishtime":636503616000000000,"title":"《一日情人》我以前也像你一样","summary":"1.恋爱中的人忘却了思考,舒服就好,幸福得如同傻子一样;\r\n\r\n2.男人如果要背叛你,不会提前告诉你的,而你能做的,就是跟他做同样的事;\r\n\r\n3.性格决定命运,同样决定着爱情的模样;\r\n\r\n4.导演镜头里的女演员,非常好看。","image":"images/EC1B95F11AF446539335EEFD1A713BB2.png"},{"id":100480,"type":1,"publishtime":636502752000000000,"title":"《伯德小姐 》成长里那些必然的抗争","summary":"这样简单温情的小品,在家人、爱情、和友谊之间周旋,却始终没有偏离成长这个棘手却永恒的问题。这部电影又好似一个珠宝盒,把最讨喜最会演戏的一帮年轻人囊括其中,让这部电影瞬间真切又充满活力。","image":"images/63ABEB90013921ACD7410E2F20F71B92.png"},{"id":100479,"type":1,"publishtime":636501888000000000,"title":"《自由之丘》句序自由,故事才自由","summary":"它可能是一部探讨时间的电影,男主人公手里总是拿着一本标题就是\u201c时间\u201d的书籍。故事从女教师在语言学校的前台收到日本男人的信件开始,男人告诉她,他已经来到她的城市,住在她周围,去她常去的咖啡馆,却寻她无果\u2026\u2026这是分写在一沓纸片上的自叙文,女教师不小心打翻了它们,每片都记录着男人的等待,和日常生活。当她从新拾起来阅读,男人要倾诉的这些日子的顺序自然被打乱了。","image":"images/AD8D78CFA74EDA7A15A12ABE92140325.png"},{"id":100478,"type":1,"publishtime":636501024000000000,"title":"《冰上轻驰》尊严与青春","summary":"本片根据一则真人真事改变而成,讲述奥运史上一段传奇故事。于1988年,四个来自牙买加的运动员,竟然凭着意志进军冬季奥运会,并在雪橇滑行比赛当中取得骄人成绩,同时赢得各国运动员的支持与鼓励。骤眼看来,将这样的史实板上银幕,无疑属励志片格局,但令观众想不到的,使全片拍摄手法轻松风趣,充满喜剧成分,而演员本身亦能发挥搞笑效果,令影片生色不少。","image":"images/8608B9B9A24C99F3DD2909782D08BCD7.png"},{"id":100007,"type":1,"publishtime":636500160000000000,"title":"《勇敢传说》合格的童话故事,一流的画面效果,不到位的女性主义","summary":"这仍旧是一部水准很高的动画电影。抛开技术层面不谈,单是这次在风格上的转型尝试就足见勇气和诚意。","image":"images/5FCE711751120087FDAB5770220AB890.jpg"},{"id":100477,"type":1,"publishtime":636499296000000000,"title":"《脸庞,村庄》汹涌无尽的悉达多之颜","summary":"他不再看见自己朋友悉达多的脸,却代之以其他的脸庞,许许多多、长长一大串的脸\u2026\u2026这人的笑容让他回忆起所有的一切,回忆起自己一生中当年曾经爱过的一切,回忆起自己一生中当年曾经认为有价值和神圣的一切。","image":"images/7780E9749657E47271B47B91CE426639.png"},{"id":100476,"type":1,"publishtime":636498432000000000,"title":"《一呼一吸》那些所谓的英雄主义,无非是想活得像正常人一样罢了","summary":"爱如空气,一呼一吸。\r\n\r\n你听懂了那句\u201cI don't want to just survive. I want to truly live.\u201d但是又有多少人能明白,对于一个瘫痪的人,到底需要放弃多少次自杀的念头才能有可能拥有所谓的truly live?","image":"images/D3C35057A1646E1A30035CAE250C8ECF.png"}] * status : 0 * errMsg : null */ private int status; private Object errMsg; private Listresult; public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } public Object getErrMsg() { return errMsg; } public void setErrMsg(Object errMsg) { this.errMsg = errMsg; } public List getResult() { return result; } public void setResult(List result) { this.result = result; } public static class ResultBean { /** * id : 100483 * type : 1 * publishtime : 636505344000000000 * title : 《离开的女人》计划好退场却全神贯注看完四小时 * summary : 这是一部接近伟大的电影,虽然结尾有些拖沓。另外电影可以剪辑到3个小时,但这部电影无论如何不能剪到3个小时以下。 女主人公被富人陷害,在监狱里关了20年,被宣布无罪释放之后,她回家把地卖了,卖地的钱用来施行复仇,这本身就说明她的社会经济地位并不算太低。在反复踩点观察下手时机的过程中,她接触到菲律宾社会最底层的小百姓,生活对他们来说每天都是地狱。女主人公因此放弃复仇计划,回城市去找她失散的儿子。 电影中Hollanda 为了报答女主人公善良,趁女主人公喝醉之际,偷了她的枪去杀她的仇人。电影里Hollanda 刺杀成功。但我觉得应该拍成刺杀不成功,反而被富人的保镖打死。这样的结局更自然,也更显悲剧。 导演Lav Diaz 对菲律宾社会的底层小人物充满了同情,他早年做新闻记者的经历对他拍摄电影有很大的帮助。 * image : images/342742C2CD5CC6FD60D142038C88D548.png */ private int id; private int type; private long publishtime; private String title; private String summary; private String image; public int getId() { return id; } public void setId(int id) { this.id = id; } public int getType() { return type; } public void setType(int type) { this.type = type; } public long getPublishtime() { return publishtime; } public void setPublishtime(long publishtime) { this.publishtime = publishtime; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getSummary() { return summary; } public void setSummary(String summary) { this.summary = summary; } public String getImage() { return image; } public void setImage(String image) { this.image = image; } } }
httpservice文件夹下MovieHttpService.java
package com.example.day09_zuoye.httpservice; import com.example.day09_zuoye.bean.MovieBean; import io.reactivex.Observable; import retrofit2.http.GET; public interface MovieHttpService { @GET("api/Critic/GetCriticList") Observable<MovieBean> getObservable(); }
viewholder文件夹下:
MovieFooterViewHolder.java
package com.example.day09_zuoye.viewholder; import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.TextView; import com.example.day09_zuoye.R; /** * Created by estyle on 2018/1/4. */ public class MovieFooterViewHolder extends RecyclerView.ViewHolder { TextView mFooterTextView; public MovieFooterViewHolder(View itemView) { super(itemView); mFooterTextView = itemView.findViewById( R.id.footer_tv); } }
MovieHeaderViewHolder.java
package com.example.day09_zuoye.viewholder; import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.TextView; import com.example.day09_zuoye.R; /** * Created by estyle on 2018/1/4. */ public class MovieHeaderViewHolder extends RecyclerView.ViewHolder { TextView mHeaderTextView; public MovieHeaderViewHolder(View itemView) { super(itemView); mHeaderTextView = itemView.findViewById( R.id.header_tv); } public void bind(String title) { mHeaderTextView.setText(title); } }
MovieViewHolder.java
package com.example.day09_zuoye.viewholder; import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import com.bumptech.glide.Glide; import com.example.day09_zuoye.R; import com.example.day09_zuoye.bean.MovieBean; public class MovieViewHolder extends RecyclerView.ViewHolder { TextView mTitleTextView; ImageView mPicImageView; public MovieViewHolder(View itemView) { super(itemView); mTitleTextView = itemView.findViewById( R.id.title_tv); mPicImageView = itemView.findViewById(R.id.pic_iv); } public void bind(MovieBean.ResultBean result) { mTitleTextView.setText(result.getTitle()); Glide.with(mPicImageView.getContext()) .load("http://api.shigeten.net/" + result.getImage()) .into(mPicImageView); } }