依赖
implementation project(':library') implementation 'com.squareup.retrofit2:retrofit:2.4.0' implementation 'com.squareup.retrofit2:converter-gson:2.4.0' implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0' implementation 'io.reactivex.rxjava2:rxjava:2.1.13' implementation 'io.reactivex.rxjava2:rxandroid:2.0.2' implementation 'com.google.dagger:dagger:2.8' annotationProcessor 'com.google.dagger:dagger-compiler:2.7' implementation 'com.facebook.fresco:fresco:0.12.0' // 支持 GIF 动图,需要添加 implementation 'com.facebook.fresco:animated-gif:0.12.0' implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0' implementation 'com.android.support:support-v4:27.1.1' implementation 'com.android.support:recyclerview-v7:27.1.1'
布局
activity_main
<LinearLayout 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" android:orientation="vertical" tools:context=".MainActivity"> <com.viewpagerindicator.TabPageIndicator android:id="@+id/titles" android:layout_width="match_parent" android:layout_height="wrap_content" /> <android.support.v4.view.ViewPager android:id="@+id/vp" android:layout_width="match_parent" android:layout_height="match_parent"></android.support.v4.view.ViewPager> </LinearLayout>
fragment_img
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v7.widget.RecyclerView android:id="@+id/rv" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
fragment_vodeo
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v7.widget.RecyclerView android:id="@+id/rv" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
img_item
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:face="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="60dp" android:orientation="horizontal" > <com.facebook.drawee.view.SimpleDraweeView android:id="@+id/imgtou1" android:layout_marginTop="5dp" android:layout_width="50dp" android:layout_height="50dp" face:roundAsCircle="true" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/text4" android:layout_marginLeft="15dp" /> </LinearLayout> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/text3" /> <com.facebook.drawee.view.SimpleDraweeView android:layout_width="match_parent" android:layout_height="300dp" android:id="@+id/img" /> </LinearLayout>
vedio_item
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:face="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="60dp" android:orientation="horizontal" > <com.facebook.drawee.view.SimpleDraweeView android:id="@+id/imgtou" android:layout_width="50dp" android:layout_height="50dp" android:layout_marginTop="5dp" face:roundAsCircle="true" /> <TextView android:id="@+id/text2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="15dp" /> </LinearLayout> <TextView android:id="@+id/text1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <VideoView android:id="@+id/surface_view" android:layout_width="match_parent" android:layout_height="200dp" /> </LinearLayout>
app
注册
public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); Fresco.initialize(this); } }
@Component(modules = HttpModule.class) public interface HttpComponent { void inject(ImgFragmet imgFragmet); void inject(VideoFragment videoFragment); }
@Module public class HttpModule { @Provides OkHttpClient.Builder provideOkHttpClientBuilder() { HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); return new OkHttpClient.Builder() .addInterceptor(loggingInterceptor) .writeTimeout(20, TimeUnit.SECONDS) .readTimeout(20, TimeUnit.SECONDS) .connectTimeout(10, TimeUnit.SECONDS); } @Provides WeekApi provideWeekApi(OkHttpClient.Builder builder) { WeekApiService weekApiService = new Retrofit.Builder() .baseUrl("https://www.apiopen.top/") .client(builder.build()) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build() .create(WeekApiService.class); return WeekApi.getWeekApi(weekApiService); } }
public class WeekApi { private static WeekApi weekApi; private WeekApiService weekApiService; public WeekApi(WeekApiService weekApiService) { this.weekApiService = weekApiService; } public static WeekApi getWeekApi(WeekApiService weekApiService) { if (weekApi == null) { weekApi = new WeekApi(weekApiService); } return weekApi; } public Observable<ImgBean> getImage() { return weekApiService.getImage(); } public Observable<VideoBean> getVideo() { return weekApiService.getVideo(); } }
public interface WeekApiService { @GET("satinApi?type=3&page=1") Observable<ImgBean> getImage(); @GET("satinApi?type=4&page=1") Observable<VideoBean> getVideo(); }
public class MainActivity extends AppCompatActivity { private TabPageIndicator mTabPageIndicator; private ViewPager mVp; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); FragmentPagerAdapter adapter = new TabPageIndicatorAdapter(getSupportFragmentManager()); mVp.setAdapter(adapter); mTabPageIndicator.setViewPager(mVp); } private void initView() { mTabPageIndicator = (TabPageIndicator) findViewById(R.id.titles); mVp = (ViewPager) findViewById(R.id.vp); } }
ui
adapter
public class ImgAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private Context context; private List<ImgBean.DataBean> data; private LayoutInflater inflater; public ImgAdapter(Context context, List<ImgBean.DataBean> data) { this.context = context; this.data = data; inflater = LayoutInflater.from(context); } @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = inflater.inflate(R.layout.img_item, parent, false); return new ImgViewHolder(view); } @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { ImgViewHolder imgViewHolder = (ImgViewHolder) holder; ImgBean.DataBean dataBean = data.get(position); imgViewHolder.imgtou1.setImageURI(dataBean.getProfile_image()); imgViewHolder.text4.setText(dataBean.getName()); imgViewHolder.text3.setText(dataBean.getText()); if (dataBean.isIs_gif()) { PipelineDraweeController controller = (PipelineDraweeController) Fresco.newDraweeControllerBuilder() .setUri(dataBean.getImage0()) .setAutoPlayAnimations(true) //自动播放gif动画 .build(); imgViewHolder.img.setController(controller); } else { imgViewHolder.img.setImageURI(dataBean.getImage0()); } } @Override public int getItemCount() { return data.size(); } class ImgViewHolder extends RecyclerView.ViewHolder { private final SimpleDraweeView imgtou1; private final TextView text4; private final TextView text3; private final SimpleDraweeView img; public ImgViewHolder(View itemView) { super(itemView); imgtou1 = itemView.findViewById(R.id.imgtou1); text4 = itemView.findViewById(R.id.text4); text3 = itemView.findViewById(R.id.text3); img = itemView.findViewById(R.id.img); } } public void setData(List<ImgBean.DataBean> list){ if (data!=null){ data.clear(); data.addAll(list); notifyDataSetChanged(); } } }
public class TabPageIndicatorAdapter extends FragmentPagerAdapter { /** * Tab标题 */ private static final String[] TITLE = new String[]{"图片", "视频", "另一面", "女人", "财经", "数码", "情感", "科技"}; public TabPageIndicatorAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { Fragment fragment = null; if (position % 2 == 0) { fragment = new ImgFragmet(); } else { fragment = new VideoFragment(); } return fragment; } @Nullable @Override public CharSequence getPageTitle(int position) { return TITLE[position % TITLE.length]; } @Override public int getCount() { return TITLE.length; } }
public class VideoAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private Context context; private List<VideoBean.DataBean> data; private LayoutInflater inflater; public VideoAdapter(Context context, List<VideoBean.DataBean> data) { this.context = context; this.data = data; inflater = LayoutInflater.from(context); } @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = inflater.inflate(R.layout.vedio_item, parent, false); return new VideoViewHolder(view); } @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { VideoViewHolder videoViewHolder = (VideoViewHolder) holder; VideoBean.DataBean dataBean = data.get(position); videoViewHolder.imgtou.setImageURI(dataBean.getProfile_image()); videoViewHolder.text1.setText(dataBean.getText()); videoViewHolder.text2.setText(dataBean.getName()); videoViewHolder.videoView.setVideoPath(dataBean.getVideouri()); videoViewHolder.videoView.start(); } @Override public int getItemCount() { return data.size(); } class VideoViewHolder extends RecyclerView.ViewHolder { private final SimpleDraweeView imgtou; private final TextView text2; private final TextView text1; private final VideoView videoView; public VideoViewHolder(View itemView) { super(itemView); imgtou = itemView.findViewById(R.id.imgtou); text2 = itemView.findViewById(R.id.text2); text1 = itemView.findViewById(R.id.text1); videoView = itemView.findViewById(R.id.surface_view); } } public void setData(List<VideoBean.DataBean> list) { if (data != null) { data.clear(); data.addAll(list); notifyDataSetChanged(); } } }
base
public interface BaseContract { interface BasePresenter<T extends BaseView> { void attachView(T view); void detachView(); } interface BaseView { void showLoading(); } }
public abstract class BaseFragment<T extends BaseContract.BasePresenter> extends Fragment implements IBase, BaseContract.BaseView { @Inject protected T mPresenter; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { inject(); View view = inflater.inflate(getContentLayout(), null); initView(view); if (mPresenter != null) { mPresenter.attachView(this); } return view; } @Override public void onDestroy() { super.onDestroy(); if (mPresenter != null) { mPresenter.detachView(); } } @Override public void showLoading() { } }
public class BasePresenter<T extends BaseContract.BaseView> implements BaseContract.BasePresenter<T> { protected T mView; @Override public void attachView(T view) { if (view != null) { this.mView = view; } } @Override public void detachView() { if (mView != null) { mView = null; } } }
contract
public interface WeekContract { interface View extends BaseContract.BaseView { void imgSuccess(List<ImgBean.DataBean> data); void videoSuccess(List<VideoBean.DataBean> data); } interface Presenter extends BaseContract.BasePresenter<View> { void getImage(); void getVideo(); } }
fragment
public class ImgFragmet extends BaseFragment<WeekPresenter> implements WeekContract.View { private List<ImgBean.DataBean> data = new ArrayList<>(); private ImgAdapter imgAdapter; @Override public int getContentLayout() { return R.layout.fragment_img; } @Override public void inject() { DaggerHttpComponent.builder() .build() .inject(this); } @Override public void initView(View view) { RecyclerView rv = view.findViewById(R.id.rv); //设置布局管理器 rv.setLayoutManager(new LinearLayoutManager(getContext())); //加分割线 rv.addItemDecoration(new DividerItemDecoration(getContext(),RecyclerView.VERTICAL)); //设置适配器 imgAdapter = new ImgAdapter(getContext(), data); rv.setAdapter(imgAdapter); //先去请求数据 mPresenter.getImage(); } @Override public void imgSuccess(List<ImgBean.DataBean> data) { if (imgAdapter!=null){ imgAdapter.setData(data); } } @Override public void videoSuccess(List<VideoBean.DataBean> data) { } }
public class VideoFragment extends BaseFragment<WeekPresenter> implements WeekContract.View{ private List<VideoBean.DataBean> data = new ArrayList<>(); private VideoAdapter videoAdapter; @Override public void imgSuccess(List<ImgBean.DataBean> data) { } @Override public int getContentLayout() { return R.layout.fragment_video; } @Override public void inject() { DaggerHttpComponent.builder() .build() .inject(this); } @Override public void initView(View view) { RecyclerView rv= view.findViewById(R.id.rv); //设置布局管理器 rv.setLayoutManager(new LinearLayoutManager(getContext())); //加分割线 rv.addItemDecoration(new DividerItemDecoration(getContext(),RecyclerView.VERTICAL)); //设置适配器 videoAdapter = new VideoAdapter(getContext(), data); rv.setAdapter(videoAdapter); //请求数据 mPresenter.getVideo(); } @Override public void videoSuccess(List<VideoBean.DataBean> data) { if (videoAdapter!=null){ videoAdapter.setData(data); } } }
inter
public interface IBase { int getContentLayout(); void inject(); void initView(View view); }
presenter
public class WeekPresenter extends BasePresenter<WeekContract.View> implements WeekContract.Presenter { private WeekApi weekApi; @Inject public WeekPresenter(WeekApi weekApi) { this.weekApi = weekApi; } @Override public void getImage() { weekApi.getImage() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .map(new Function<ImgBean, List<ImgBean.DataBean>>() { @Override public List<ImgBean.DataBean> apply(ImgBean imgBean) throws Exception { return imgBean.getData(); } }).subscribe(new Consumer<List<ImgBean.DataBean>>() { @Override public void accept(List<ImgBean.DataBean> dataBeans) throws Exception { if (mView != null) { mView.imgSuccess(dataBeans); } } }); } @Override public void getVideo() { weekApi.getVideo() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .map(new Function<VideoBean, List<VideoBean.DataBean>>() { @Override public List<VideoBean.DataBean> apply(VideoBean videoBean) throws Exception { return videoBean.getData(); } }).subscribe(new Consumer<List<VideoBean.DataBean>>() { @Override public void accept(List<VideoBean.DataBean> dataBeans) throws Exception { if (mView != null) { mView.videoSuccess(dataBeans); } } }); } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.week2demo"> <uses-permission android:name="android.permission.INTERNET"></uses-permission> <uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <application android:name="com.example.app.MyApp" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> </manifest>