From f7d36b0f2c254a048905ae27c9e421427eb0f2c8 Mon Sep 17 00:00:00 2001
From: Administrator <123>
Date: Thu, 04 Nov 2021 02:04:19 +0000
Subject: [PATCH] tablayout 框架   分页加载框架

---
 app/src/main/java/com/duqing/missions/ui/main/hall/SubHallFragment.java         |    4 
 app/src/main/java/com/duqing/missions/ui/main/hall/SubHallViewModel.java        |   20 ++
 app/src/main/java/com/duqing/missions/ui/main/hall/HallViewModel.java           |   12 -
 app/src/main/java/com/duqing/missions/base/activities/BaseLoadPageActivity.java |   84 ++++++++
 app/src/main/java/com/duqing/missions/base/activities/BaseActivity.java         |   13 +
 app/src/main/java/com/duqing/missions/base/activities/BaseTabActivity.java      |   78 +++++++
 app/src/main/java/com/duqing/missions/base/fragments/BaseTabFragment.java       |   74 +++++++
 app/src/main/res/layout/fragment_home.xml                                       |    2 
 app/src/main/java/com/duqing/missions/base/FragmentAdapter.java                 |    2 
 app/src/main/res/layout/layout_tab_viewpager.xml                                |   32 +++
 app/src/main/java/com/duqing/missions/base/activity.java                        |    7 
 app/src/main/java/com/duqing/missions/base/fragments/BaseLoadPageFragment.java  |   93 +++++++++
 app/src/main/res/layout/fragment_hall.xml                                       |    4 
 app/src/main/java/com/duqing/missions/base/BaseAdapter.java                     |    1 
 app/src/main/java/com/duqing/missions/ui/main/hall/HallFragment.java            |   37 ++-
 app/src/main/java/com/duqing/missions/base/activities/BaseTitleBarActivity.java |    6 
 app/src/main/java/com/duqing/missions/ui/login/view/LoginActivity.java          |    2 
 app/src/main/java/com/duqing/missions/base/fragments/BaseFragment.java          |   17 +
 app/src/main/java/com/duqing/missions/base/model/BaseLoadPageViewModel.java     |   15 +
 app/src/main/java/com/duqing/missions/ui/main/home/HomeFragment.java            |   45 ---
 app/src/main/java/com/duqing/missions/ui/main/mine/MineFragment.java            |    9 
 app/src/main/java/com/duqing/missions/MainActivity.java                         |    2 
 app/src/main/java/com/duqing/missions/ui/main/home/HomeViewModel.java           |   15 -
 23 files changed, 480 insertions(+), 94 deletions(-)

diff --git a/app/src/main/java/com/duqing/missions/MainActivity.java b/app/src/main/java/com/duqing/missions/MainActivity.java
index f903b3b..09a3b32 100644
--- a/app/src/main/java/com/duqing/missions/MainActivity.java
+++ b/app/src/main/java/com/duqing/missions/MainActivity.java
@@ -2,8 +2,8 @@
 
 import androidx.viewpager2.widget.ViewPager2;
 
-import com.duqing.missions.base.BaseActivity;
 import com.duqing.missions.base.FragmentAdapter;
+import com.duqing.missions.base.activities.BaseActivity;
 import com.duqing.missions.databinding.ActivityMainBinding;
 import com.duqing.missions.ui.main.hall.HallFragment;
 import com.duqing.missions.ui.main.home.HomeFragment;
diff --git a/app/src/main/java/com/duqing/missions/base/BaseAdapter.java b/app/src/main/java/com/duqing/missions/base/BaseAdapter.java
index 520e455..735ccef 100644
--- a/app/src/main/java/com/duqing/missions/base/BaseAdapter.java
+++ b/app/src/main/java/com/duqing/missions/base/BaseAdapter.java
@@ -11,6 +11,7 @@
 import androidx.viewbinding.ViewBinding;
 
 import com.duqing.missions.R;
+import com.duqing.missions.base.activities.BaseActivity;
 import com.duqing.missions.common.NullViewHolder;
 import com.duqing.missions.databinding.LayoutNullBinding;
 import com.duqing.missions.util.DeviceUtil;
diff --git a/app/src/main/java/com/duqing/missions/base/FragmentAdapter.java b/app/src/main/java/com/duqing/missions/base/FragmentAdapter.java
index 9a4f646..3d5bb42 100644
--- a/app/src/main/java/com/duqing/missions/base/FragmentAdapter.java
+++ b/app/src/main/java/com/duqing/missions/base/FragmentAdapter.java
@@ -5,6 +5,8 @@
 import androidx.fragment.app.FragmentActivity;
 import androidx.viewpager2.adapter.FragmentStateAdapter;
 
+import com.duqing.missions.base.fragments.BaseFragment;
+
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/app/src/main/java/com/duqing/missions/base/BaseActivity.java b/app/src/main/java/com/duqing/missions/base/activities/BaseActivity.java
similarity index 96%
rename from app/src/main/java/com/duqing/missions/base/BaseActivity.java
rename to app/src/main/java/com/duqing/missions/base/activities/BaseActivity.java
index 3d37b2c..ada8707 100644
--- a/app/src/main/java/com/duqing/missions/base/BaseActivity.java
+++ b/app/src/main/java/com/duqing/missions/base/activities/BaseActivity.java
@@ -1,4 +1,4 @@
-package com.duqing.missions.base;
+package com.duqing.missions.base.activities;
 
 import android.Manifest;
 import android.app.AlertDialog;
@@ -26,6 +26,8 @@
 import androidx.annotation.StringRes;
 import androidx.appcompat.app.AppCompatActivity;
 import androidx.core.content.FileProvider;
+import androidx.lifecycle.ViewModel;
+import androidx.lifecycle.ViewModelProvider;
 import androidx.viewbinding.ViewBinding;
 
 import com.duqing.missions.MyApplication;
@@ -58,11 +60,13 @@
 import okhttp3.ResponseBody;
 
 /**
+ * activity 封装
  * Created by Administrator on 2021/10/27 0027.
  */
-public abstract class BaseActivity<B extends ViewBinding> extends AppCompatActivity {
+public abstract class BaseActivity<B extends ViewBinding,VM extends ViewModel> extends AppCompatActivity {
 
     protected  B binding;
+    protected  VM viewModel;
     protected String TAG ;
     public final String[] FILE_PERMISSIONS = new String []{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE};
     public final String[] LOCATION_PERMISSIONS = new String []{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION};
@@ -106,10 +110,13 @@
         // get genericity "B"
         setStatusBarBgColor(R.color.white);
         setStatusBarTextColor(true);
-        Class<B> entityClass = (Class<B>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
         try {
+            final ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
+            Class<B> entityClass = (Class<B>) type.getActualTypeArguments()[0];
             Method method = entityClass.getMethod("inflate", LayoutInflater.class);//get method from name "inflate";
             binding = (B) method.invoke(entityClass,getLayoutInflater());//execute method to create a objct of viewbind;
+            Class<VM> vmClass = (Class<VM>) type.getActualTypeArguments()[1];
+            viewModel = new ViewModelProvider(this).get(vmClass);
         } catch (Exception e) {
             e.printStackTrace();
         }
diff --git a/app/src/main/java/com/duqing/missions/base/activities/BaseLoadPageActivity.java b/app/src/main/java/com/duqing/missions/base/activities/BaseLoadPageActivity.java
new file mode 100644
index 0000000..ef17679
--- /dev/null
+++ b/app/src/main/java/com/duqing/missions/base/activities/BaseLoadPageActivity.java
@@ -0,0 +1,84 @@
+package com.duqing.missions.base.activities;
+
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.viewbinding.ViewBinding;
+
+import com.duqing.missions.base.BaseAdapter;
+import com.duqing.missions.base.model.BaseLoadPageViewModel;
+import com.duqing.missions.data.BasePageResult;
+import com.scwang.smart.refresh.footer.ClassicsFooter;
+import com.scwang.smart.refresh.header.ClassicsHeader;
+import com.scwang.smart.refresh.layout.SmartRefreshLayout;
+import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener;
+
+import java.lang.reflect.ParameterizedType;
+import java.util.HashMap;
+
+/**
+ * Created by Administrator on 2021/11/4 0004.
+ */
+public abstract class BaseLoadPageActivity<B extends ViewBinding,VM extends BaseLoadPageViewModel,A extends BaseAdapter,D extends BasePageResult>
+        extends BaseTitleBarActivity<B,VM>  implements OnRefreshLoadMoreListener {
+
+    protected SmartRefreshLayout smartRefresh;
+    protected RecyclerView recycler;
+    final String TAG = "RecyclerFragment";
+    protected A adapter;//适配器
+    protected String url;//请求地址
+    protected HashMap param;//参数
+    protected int page=1;
+    protected final int SIZE = 10;
+    protected boolean isRefresh = false;//是否正在刷新
+    
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Class<A> entityClass = (Class<A>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[2];
+        try {
+            this.adapter = entityClass.newInstance();//实例化泛型
+            smartRefresh = (SmartRefreshLayout) binding.getClass().getDeclaredField("smartRefresh").get(binding);
+            smartRefresh.setRefreshHeader(new ClassicsHeader(mContext));
+            smartRefresh.setRefreshFooter(new ClassicsFooter(mContext));
+            smartRefresh.setOnRefreshLoadMoreListener(this);
+            recycler =  (RecyclerView) binding.getClass().getDeclaredField("recycler").get(binding);
+            recycler.setLayoutManager(new LinearLayoutManager(mContext));
+            recycler.setAdapter(adapter);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void finishFreshLoadmore(D result){
+        if(result.code == 200){
+
+            smartRefresh.setEnableRefresh(true);
+            smartRefresh.finishRefresh();
+            if(page == 1){
+                adapter.getData().clear();
+                adapter.setData(result.rows);
+            }else{
+                adapter.getData().addAll(result.rows);
+                adapter.notifyDataSetChanged();
+            }
+            if(result.total <= adapter.getData().size()// 总数是否已经加载完
+                    || result.rows.size() < SIZE // 最后一页数据的数量一般不满size
+            ){//判断是否没有数据了
+                smartRefresh.finishLoadMoreWithNoMoreData();
+            }else {
+                smartRefresh.finishLoadMore();
+            }
+        }else{
+            smartRefresh.setEnableRefresh(true);
+            smartRefresh.finishRefresh();
+            smartRefresh.finishLoadMore();
+        }
+    }
+
+    public A getAdapter() {
+        return adapter;
+    }
+}
diff --git a/app/src/main/java/com/duqing/missions/base/activities/BaseTabActivity.java b/app/src/main/java/com/duqing/missions/base/activities/BaseTabActivity.java
new file mode 100644
index 0000000..1afd695
--- /dev/null
+++ b/app/src/main/java/com/duqing/missions/base/activities/BaseTabActivity.java
@@ -0,0 +1,78 @@
+package com.duqing.missions.base.activities;
+
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.lifecycle.ViewModel;
+import androidx.viewbinding.ViewBinding;
+import androidx.viewpager2.widget.ViewPager2;
+
+import com.duqing.missions.base.FragmentAdapter;
+import com.duqing.missions.base.fragments.BaseFragment;
+import com.google.android.material.tabs.TabLayout;
+import com.google.android.material.tabs.TabLayoutMediator;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Created by Administrator on 2021/11/4 0004.
+ */
+public abstract class BaseTabActivity<B extends ViewBinding,VM extends ViewModel>  extends BaseActivity<B,VM> {
+
+    TabLayout tabLayout;
+    FragmentAdapter fragmentAdapter;
+    List<String> tabTitles = new ArrayList<>();
+    ViewPager2 viewPager2;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        fragmentAdapter = new FragmentAdapter(this);
+        fragmentAdapter.setFragments(initFragments());
+        setTabTitles(initTabTitles());
+        //设置当前可见Item左右可见page数,次范围内不会被销毁
+        //禁用预加载
+        try {
+            viewPager2 = (ViewPager2) binding.getClass().getDeclaredField("viewPager2").get(binding);
+            tabLayout = (TabLayout) binding.getClass().getDeclaredField("tabLayout").get(binding);
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+        } catch (NoSuchFieldException e) {
+            e.printStackTrace();
+        }
+        ;
+        viewPager2.setOffscreenPageLimit(ViewPager2.OFFSCREEN_PAGE_LIMIT_DEFAULT);
+        viewPager2.setAdapter(fragmentAdapter);
+        viewPager2.setCurrentItem(0);
+        viewPager2.setUserInputEnabled(false); //true:滑动,false:禁止滑动
+        new TabLayoutMediator(tabLayout, viewPager2, (tab, position) -> tab.setText(tabTitles.get(position))).attach();
+    }
+
+
+    protected abstract List<String> initTabTitles();
+
+    protected abstract List<BaseFragment> initFragments();
+
+    protected List<String> getTabTitles(){
+        return tabTitles;
+    }
+
+    public FragmentAdapter getFragmentAdapter() {
+        return fragmentAdapter;
+    }
+
+    public void setTabTitles(List<String> tabTitles) {
+        if(tabTitles == null){
+            this.tabTitles.clear();
+        }
+        this.tabTitles = tabTitles;
+    }
+    public void setTabTitles(String[] tabTitles) {
+        if(tabTitles == null){
+            this.tabTitles.clear();
+        }
+        setTabTitles(new ArrayList<>(Arrays.asList(tabTitles)));
+    }
+}
diff --git a/app/src/main/java/com/duqing/missions/base/BaseTitleBarActivity.java b/app/src/main/java/com/duqing/missions/base/activities/BaseTitleBarActivity.java
similarity index 90%
rename from app/src/main/java/com/duqing/missions/base/BaseTitleBarActivity.java
rename to app/src/main/java/com/duqing/missions/base/activities/BaseTitleBarActivity.java
index 8a56999..dab729e 100644
--- a/app/src/main/java/com/duqing/missions/base/BaseTitleBarActivity.java
+++ b/app/src/main/java/com/duqing/missions/base/activities/BaseTitleBarActivity.java
@@ -1,18 +1,20 @@
-package com.duqing.missions.base;
+package com.duqing.missions.base.activities;
 
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.view.ViewGroup;
 
 import androidx.annotation.Nullable;
+import androidx.lifecycle.ViewModel;
 import androidx.viewbinding.ViewBinding;
 
 import com.duqing.missions.widgets.TitleBarView;
 
 /**
+ * 带有标题栏的activity封装
  * Created by Administrator on 2021/11/2 0002.
  */
-public abstract class BaseTitleBarActivity<B extends ViewBinding> extends BaseActivity<B> {
+public abstract class BaseTitleBarActivity<B extends ViewBinding,VM extends ViewModel> extends BaseActivity<B,VM> {
     TitleBarView titleBarView;
 
     @Override
diff --git a/app/src/main/java/com/duqing/missions/base/activity.java b/app/src/main/java/com/duqing/missions/base/activity.java
new file mode 100644
index 0000000..6a431e6
--- /dev/null
+++ b/app/src/main/java/com/duqing/missions/base/activity.java
@@ -0,0 +1,7 @@
+package com.duqing.missions.base;
+
+/**
+ * Created by Administrator on 2021/11/3 0003.
+ */
+public class activity {
+}
diff --git a/app/src/main/java/com/duqing/missions/base/BaseFragment.java b/app/src/main/java/com/duqing/missions/base/fragments/BaseFragment.java
similarity index 65%
rename from app/src/main/java/com/duqing/missions/base/BaseFragment.java
rename to app/src/main/java/com/duqing/missions/base/fragments/BaseFragment.java
index 099381b..882ed3d 100644
--- a/app/src/main/java/com/duqing/missions/base/BaseFragment.java
+++ b/app/src/main/java/com/duqing/missions/base/fragments/BaseFragment.java
@@ -1,4 +1,4 @@
-package com.duqing.missions.base;
+package com.duqing.missions.base.fragments;
 
 import android.os.Bundle;
 import android.view.LayoutInflater;
@@ -7,27 +7,36 @@
 
 import androidx.annotation.Nullable;
 import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModel;
+import androidx.lifecycle.ViewModelProvider;
 import androidx.viewbinding.ViewBinding;
+
+import com.duqing.missions.base.activities.BaseActivity;
 
 import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
 
 /**
+ * fragment 封装
  * Created by Administrator on 2021/10/28 0028.
  */
-public abstract class BaseFragment<B extends ViewBinding> extends Fragment {
+public abstract class BaseFragment<B extends ViewBinding,VM extends ViewModel> extends Fragment {
 
-    protected  BaseActivity activity;
+    protected BaseActivity activity;
     protected  B binding;
+    protected  VM viewModel;
 
     @Nullable
     @Override
     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
         // get genericity "B"
-        Class<B> entityClass = (Class<B>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
         try {
+            final ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
+            Class<B> entityClass = (Class<B>) type.getActualTypeArguments()[0];
             Method method = entityClass.getMethod("inflate", LayoutInflater.class,ViewGroup.class,boolean.class);//get method from name "inflate";
             binding = (B) method.invoke(entityClass,inflater,container,false);//execute method to create a objct of viewbind;
+            Class<VM> vmClass = (Class<VM>) type.getActualTypeArguments()[1];
+            viewModel = new ViewModelProvider(this).get(vmClass);
         } catch (Exception e) {
             e.printStackTrace();
         }
diff --git a/app/src/main/java/com/duqing/missions/base/fragments/BaseLoadPageFragment.java b/app/src/main/java/com/duqing/missions/base/fragments/BaseLoadPageFragment.java
new file mode 100644
index 0000000..327311a
--- /dev/null
+++ b/app/src/main/java/com/duqing/missions/base/fragments/BaseLoadPageFragment.java
@@ -0,0 +1,93 @@
+package com.duqing.missions.base.fragments;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.viewbinding.ViewBinding;
+
+import com.duqing.missions.base.BaseAdapter;
+import com.duqing.missions.base.model.BaseLoadPageViewModel;
+import com.duqing.missions.data.BasePageResult;
+import com.scwang.smart.refresh.footer.ClassicsFooter;
+import com.scwang.smart.refresh.header.ClassicsHeader;
+import com.scwang.smart.refresh.layout.SmartRefreshLayout;
+import com.scwang.smart.refresh.layout.api.RefreshLayout;
+import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener;
+
+import java.lang.reflect.ParameterizedType;
+import java.util.HashMap;
+
+/**
+ * 分页fragment 封装
+ * Created by Administrator on 2021/11/3 0003.
+ */
+public abstract class BaseLoadPageFragment<B extends ViewBinding,VM extends BaseLoadPageViewModel,A extends BaseAdapter,D extends BasePageResult> extends BaseFragment<B,VM>
+        implements OnRefreshLoadMoreListener {
+    protected SmartRefreshLayout smartRefresh;
+    protected RecyclerView recycler;
+    final String TAG = "RecyclerFragment";
+    protected A adapter;//适配器
+    protected String url;//请求地址
+    protected HashMap param;//参数
+    protected int page=1;
+    protected final int SIZE = 10;
+    protected boolean isRefresh = false;//是否正在刷新
+
+    @Override
+    public void initViews() {
+        try {
+            Class<A> entityClass = (Class<A>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[2];
+            this.adapter = entityClass.newInstance();//实例化泛型
+            smartRefresh = (SmartRefreshLayout) binding.getClass().getDeclaredField("smartRefresh").get(binding);
+            smartRefresh.setRefreshHeader(new ClassicsHeader(getContext()));
+            smartRefresh.setRefreshFooter(new ClassicsFooter(getContext()));
+            smartRefresh.setOnRefreshLoadMoreListener(this);
+            recycler =  (RecyclerView) binding.getClass().getDeclaredField("recycler").get(binding);
+            recycler.setLayoutManager(new LinearLayoutManager(getContext()));
+            recycler.setAdapter(adapter);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void onLoadMore(@NonNull RefreshLayout refreshLayout) {
+        page++;
+        viewModel.onLoadMore();
+    }
+
+    @Override
+    public void onRefresh(@NonNull RefreshLayout refreshLayout) {
+        page = 1;
+        viewModel.onRefresh();
+    }
+
+    private void finishFreshLoadmore(D result){
+        if(result.code == 200){
+
+            smartRefresh.setEnableRefresh(true);
+            smartRefresh.finishRefresh();
+            if(page == 1){
+                adapter.getData().clear();
+                adapter.setData(result.rows);
+            }else{
+                adapter.getData().addAll(result.rows);
+                adapter.notifyDataSetChanged();
+            }
+            if(result.total <= adapter.getData().size()// 总数是否已经加载完
+                    || result.rows.size() < SIZE // 最后一页数据的数量一般不满size
+            ){//判断是否没有数据了
+                smartRefresh.finishLoadMoreWithNoMoreData();
+            }else {
+                smartRefresh.finishLoadMore();
+            }
+        }else{
+            smartRefresh.setEnableRefresh(true);
+            smartRefresh.finishRefresh();
+            smartRefresh.finishLoadMore();
+        }
+    }
+    public A getAdapter() {
+        return adapter;
+    }
+}
diff --git a/app/src/main/java/com/duqing/missions/base/fragments/BaseTabFragment.java b/app/src/main/java/com/duqing/missions/base/fragments/BaseTabFragment.java
new file mode 100644
index 0000000..a70076a
--- /dev/null
+++ b/app/src/main/java/com/duqing/missions/base/fragments/BaseTabFragment.java
@@ -0,0 +1,74 @@
+package com.duqing.missions.base.fragments;
+
+import androidx.lifecycle.ViewModel;
+import androidx.viewbinding.ViewBinding;
+import androidx.viewpager2.widget.ViewPager2;
+
+import com.duqing.missions.base.FragmentAdapter;
+import com.google.android.material.tabs.TabLayout;
+import com.google.android.material.tabs.TabLayoutMediator;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 带有tablayout fragment封装
+ * Created by Administrator on 2021/11/3 0003.
+ */
+public abstract class BaseTabFragment<B extends ViewBinding,VM extends ViewModel> extends BaseFragment<B,VM> {
+
+    TabLayout tabLayout;
+    FragmentAdapter fragmentAdapter;
+    List<String> tabTitles = new ArrayList<>();
+    ViewPager2 viewPager2;
+
+    @Override
+    public void initViews() {
+
+        fragmentAdapter = new FragmentAdapter(activity);
+        fragmentAdapter.setFragments(initFragments());
+        setTabTitles(initTabTitles());
+        //设置当前可见Item左右可见page数,次范围内不会被销毁
+        //禁用预加载
+        try {
+            viewPager2 = (ViewPager2) binding.getClass().getDeclaredField("viewPager2").get(binding);
+            tabLayout = (TabLayout) binding.getClass().getDeclaredField("tabLayout").get(binding);
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+        } catch (NoSuchFieldException e) {
+            e.printStackTrace();
+        }
+        ;
+        viewPager2.setOffscreenPageLimit(ViewPager2.OFFSCREEN_PAGE_LIMIT_DEFAULT);
+        viewPager2.setAdapter(fragmentAdapter);
+        viewPager2.setCurrentItem(0);
+        viewPager2.setUserInputEnabled(false); //true:滑动,false:禁止滑动
+        new TabLayoutMediator(tabLayout, viewPager2, (tab, position) -> tab.setText(tabTitles.get(position))).attach();
+    }
+
+    protected abstract List<String> initTabTitles();
+
+    protected abstract List<BaseFragment> initFragments();
+
+    protected List<String> getTabTitles(){
+        return tabTitles;
+    }
+
+    public FragmentAdapter getFragmentAdapter() {
+        return fragmentAdapter;
+    }
+
+    public void setTabTitles(List<String> tabTitles) {
+        if(tabTitles == null){
+            this.tabTitles.clear();
+        }
+        this.tabTitles = tabTitles;
+    }
+    public void setTabTitles(String[] tabTitles) {
+        if(tabTitles == null){
+            this.tabTitles.clear();
+        }
+        setTabTitles(new ArrayList<>(Arrays.asList(tabTitles)));
+    }
+}
diff --git a/app/src/main/java/com/duqing/missions/base/model/BaseLoadPageViewModel.java b/app/src/main/java/com/duqing/missions/base/model/BaseLoadPageViewModel.java
new file mode 100644
index 0000000..a4ef5f1
--- /dev/null
+++ b/app/src/main/java/com/duqing/missions/base/model/BaseLoadPageViewModel.java
@@ -0,0 +1,15 @@
+package com.duqing.missions.base.model;
+
+import androidx.lifecycle.ViewModel;
+
+/**
+ * 分页
+ * Created by Administrator on 2021/11/3 0003.
+ */
+public abstract class BaseLoadPageViewModel extends ViewModel {
+
+    public abstract void onRefresh();
+
+    public abstract void onLoadMore();
+
+}
diff --git a/app/src/main/java/com/duqing/missions/ui/login/view/LoginActivity.java b/app/src/main/java/com/duqing/missions/ui/login/view/LoginActivity.java
index d10b2eb..551e4c9 100644
--- a/app/src/main/java/com/duqing/missions/ui/login/view/LoginActivity.java
+++ b/app/src/main/java/com/duqing/missions/ui/login/view/LoginActivity.java
@@ -19,7 +19,7 @@
 import androidx.lifecycle.ViewModelProvider;
 
 import com.duqing.missions.R;
-import com.duqing.missions.base.BaseTitleBarActivity;
+import com.duqing.missions.base.activities.BaseTitleBarActivity;
 import com.duqing.missions.databinding.ActivityLoginBinding;
 
 
diff --git a/app/src/main/java/com/duqing/missions/ui/main/hall/HallFragment.java b/app/src/main/java/com/duqing/missions/ui/main/hall/HallFragment.java
index 325e471..9127bf2 100644
--- a/app/src/main/java/com/duqing/missions/ui/main/hall/HallFragment.java
+++ b/app/src/main/java/com/duqing/missions/ui/main/hall/HallFragment.java
@@ -1,29 +1,25 @@
 package com.duqing.missions.ui.main.hall;
 
 import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.lifecycle.Observer;
-import androidx.lifecycle.ViewModelProvider;
 import androidx.viewpager2.widget.ViewPager2;
 
-import com.duqing.missions.base.BaseFragment;
 import com.duqing.missions.base.FragmentAdapter;
+import com.duqing.missions.base.fragments.BaseFragment;
+import com.duqing.missions.base.fragments.BaseTabFragment;
 import com.duqing.missions.databinding.FragmentHallBinding;
 import com.google.android.material.tabs.TabLayout;
 import com.google.android.material.tabs.TabLayoutMediator;
 
-public class HallFragment extends BaseFragment<FragmentHallBinding> {
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
-    private HallViewModel hallViewModel;
+public class HallFragment extends BaseTabFragment<FragmentHallBinding,HallViewModel> {
+
 
     @Override
     public void initViews() {
-        hallViewModel = new ViewModelProvider(this).get(HallViewModel.class);
-        hallViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() {
-            @Override
-            public void onChanged(@Nullable String s) {
-            }
-        });
+        super.initViews();
         final String[] titles = new String[]{"全部","人气","简单","高价"};
         final FragmentAdapter fragmentAdapter = new FragmentAdapter(activity);
         fragmentAdapter.addFragment(new SubHallFragment());
@@ -36,7 +32,7 @@
         binding.viewPager2.setAdapter(fragmentAdapter);
         binding.viewPager2.setCurrentItem(0);
         binding.viewPager2.setUserInputEnabled(false); //true:滑动,false:禁止滑动
-        TabLayoutMediator mediator = new TabLayoutMediator(binding.tablayout, binding.viewPager2, new TabLayoutMediator.TabConfigurationStrategy() {
+        TabLayoutMediator mediator = new TabLayoutMediator(binding.tabLayout, binding.viewPager2, new TabLayoutMediator.TabConfigurationStrategy() {
             @Override
             public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
                 tab.setText(titles[position]);
@@ -46,4 +42,19 @@
 
 
     }
+
+    @Override
+    protected List<String> initTabTitles() {
+        return new ArrayList<>(Arrays.asList(new String[]{"全部","人气","简单","高价"}));
+    }
+
+    @Override
+    protected List<BaseFragment> initFragments() {
+        List<BaseFragment> list = new ArrayList<>();
+        list.add(new SubHallFragment());
+        list.add(new SubHallFragment());
+        list.add(new SubHallFragment());
+        list.add(new SubHallFragment());
+        return list;
+    }
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/duqing/missions/ui/main/hall/HallViewModel.java b/app/src/main/java/com/duqing/missions/ui/main/hall/HallViewModel.java
index ecbe20f..85ac968 100644
--- a/app/src/main/java/com/duqing/missions/ui/main/hall/HallViewModel.java
+++ b/app/src/main/java/com/duqing/missions/ui/main/hall/HallViewModel.java
@@ -1,19 +1,7 @@
 package com.duqing.missions.ui.main.hall;
 
-import androidx.lifecycle.LiveData;
-import androidx.lifecycle.MutableLiveData;
 import androidx.lifecycle.ViewModel;
 
 public class HallViewModel extends ViewModel {
 
-    private MutableLiveData<String> mText;
-
-    public HallViewModel() {
-        mText = new MutableLiveData<>();
-        mText.setValue("This is dashboard fragment");
-    }
-
-    public LiveData<String> getText() {
-        return mText;
-    }
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/duqing/missions/ui/main/hall/SubHallFragment.java b/app/src/main/java/com/duqing/missions/ui/main/hall/SubHallFragment.java
index 3a3c00e..f8fbc44 100644
--- a/app/src/main/java/com/duqing/missions/ui/main/hall/SubHallFragment.java
+++ b/app/src/main/java/com/duqing/missions/ui/main/hall/SubHallFragment.java
@@ -1,12 +1,12 @@
 package com.duqing.missions.ui.main.hall;
 
-import com.duqing.missions.base.BaseFragment;
+import com.duqing.missions.base.fragments.BaseFragment;
 import com.duqing.missions.databinding.FragmentSubHallBinding;
 
 /**
  * Created by Administrator on 2021/11/3 0003.
  */
-public class SubHallFragment extends BaseFragment<FragmentSubHallBinding> {
+public class SubHallFragment extends BaseFragment<FragmentSubHallBinding,SubHallViewModel> {
 
 
 
diff --git a/app/src/main/java/com/duqing/missions/ui/main/hall/SubHallViewModel.java b/app/src/main/java/com/duqing/missions/ui/main/hall/SubHallViewModel.java
new file mode 100644
index 0000000..2407707
--- /dev/null
+++ b/app/src/main/java/com/duqing/missions/ui/main/hall/SubHallViewModel.java
@@ -0,0 +1,20 @@
+package com.duqing.missions.ui.main.hall;
+
+import com.duqing.missions.base.model.BaseLoadPageViewModel;
+
+/**
+ * Created by Administrator on 2021/11/3 0003.
+ */
+public class SubHallViewModel extends BaseLoadPageViewModel {
+
+
+    @Override
+    public void onRefresh() {
+
+    }
+
+    @Override
+    public void onLoadMore() {
+
+    }
+}
diff --git a/app/src/main/java/com/duqing/missions/ui/main/home/HomeFragment.java b/app/src/main/java/com/duqing/missions/ui/main/home/HomeFragment.java
index 346c357..2b6198a 100644
--- a/app/src/main/java/com/duqing/missions/ui/main/home/HomeFragment.java
+++ b/app/src/main/java/com/duqing/missions/ui/main/home/HomeFragment.java
@@ -8,83 +8,52 @@
 import android.view.ViewGroup;
 import android.widget.TextView;
 
-import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.lifecycle.Observer;
-import androidx.lifecycle.ViewModelProvider;
 import androidx.recyclerview.widget.GridLayoutManager;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
-import com.duqing.missions.base.BaseFragment;
+import com.duqing.missions.base.fragments.BaseLoadPageFragment;
+import com.duqing.missions.data.BasePageResult;
 import com.duqing.missions.databinding.FragmentHomeBinding;
 import com.duqing.missions.ui.login.view.LoginActivity;
 import com.duqing.missions.ui.main.home.adapter.MissionAdapter;
 import com.duqing.missions.ui.main.home.adapter.MissionTopAdapter;
 import com.duqing.missions.ui.main.home.model.MissionDesc;
-import com.scwang.smart.refresh.footer.ClassicsFooter;
-import com.scwang.smart.refresh.header.ClassicsHeader;
-import com.scwang.smart.refresh.layout.SmartRefreshLayout;
-import com.scwang.smart.refresh.layout.api.RefreshLayout;
-import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener;
 
 import java.util.List;
 
-public class HomeFragment extends BaseFragment<FragmentHomeBinding> {
+public class HomeFragment extends BaseLoadPageFragment<FragmentHomeBinding,HomeViewModel,MissionAdapter, BasePageResult<String>> {
 
-    private HomeViewModel homeViewModel;
     final String TAG = "HomeFragment";
 
 
     @Override
     public void initViews() {
-        homeViewModel = new ViewModelProvider(this).get(HomeViewModel.class);
+        super.initViews();
         binding.textSearch.setOnClickListener(v -> startActivity(new Intent(getContext(), LoginActivity.class)));
-        final SmartRefreshLayout smartRefresh = binding.smartRefresh;
-        smartRefresh.setRefreshHeader(new ClassicsHeader(getContext()));
-        smartRefresh.setRefreshFooter(new ClassicsFooter(getContext()));
         final  TextView textView = binding.textRecommend;
         RecyclerView recyclerClassify = binding.recyclerClassify;
         RecyclerView recyclerTop = binding.recyclerTop;
-        final RecyclerView recyclerRecommend = binding.recyclerRecommend;
-        recyclerRecommend.setLayoutManager(new LinearLayoutManager(getContext()));
         LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
         layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
         recyclerClassify.setLayoutManager(layoutManager);
         recyclerTop.setLayoutManager(new GridLayoutManager(getContext(),3));
-        smartRefresh.setOnRefreshLoadMoreListener(new OnRefreshLoadMoreListener() {
-            @Override
-            public void onLoadMore(@NonNull RefreshLayout refreshLayout) {
-                homeViewModel.onLoadMore();
-            }
-
-            @Override
-            public void onRefresh(@NonNull RefreshLayout refreshLayout) {
-                homeViewModel.onRefresh();
-            }
-        });
         final MissionTopAdapter topAdapter = new MissionTopAdapter();
         recyclerTop.setAdapter(topAdapter);
-        final MissionAdapter recommendAdapter = new MissionAdapter();
-        recyclerRecommend.setAdapter(recommendAdapter);
-        homeViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() {
-            @Override
-            public void onChanged(@Nullable String s) {
-                textView.setText(s);
-            }
-        });
-        homeViewModel.getTopMissions().observe(getViewLifecycleOwner(), new Observer<List<MissionDesc>>() {
+        viewModel.getTopMissions().observe(getViewLifecycleOwner(), new Observer<List<MissionDesc>>() {
             @Override
             public void onChanged(List<MissionDesc> missionDescs) {
                 smartRefresh.finishRefresh();
                 topAdapter.setData(missionDescs);
             }
         });
-        homeViewModel.getRecommendMissions().observeForever(new Observer<List<MissionDesc>>() {
+        viewModel.getRecommendMissions().observeForever(new Observer<List<MissionDesc>>() {
             @Override
             public void onChanged(List<MissionDesc> missionDescs) {
                 smartRefresh.finishLoadMore();
-                recommendAdapter.setData(missionDescs);
+                adapter.setData(missionDescs);
             }
         });
     }
diff --git a/app/src/main/java/com/duqing/missions/ui/main/home/HomeViewModel.java b/app/src/main/java/com/duqing/missions/ui/main/home/HomeViewModel.java
index eb69ae9..6852983 100644
--- a/app/src/main/java/com/duqing/missions/ui/main/home/HomeViewModel.java
+++ b/app/src/main/java/com/duqing/missions/ui/main/home/HomeViewModel.java
@@ -1,28 +1,21 @@
 package com.duqing.missions.ui.main.home;
 
-import androidx.lifecycle.LiveData;
 import androidx.lifecycle.MutableLiveData;
-import androidx.lifecycle.ViewModel;
 
+import com.duqing.missions.base.model.BaseLoadPageViewModel;
 import com.duqing.missions.ui.main.home.model.MissionDesc;
 
 import java.util.ArrayList;
 import java.util.List;
 
-public class HomeViewModel extends ViewModel {
+public class HomeViewModel extends BaseLoadPageViewModel {
 
-    private MutableLiveData<String> mText;
     private MutableLiveData<List<MissionDesc>> topMissions = new MutableLiveData<>();
     private MutableLiveData<List<MissionDesc>> recommendMissions = new MutableLiveData<>();
 
     public HomeViewModel() {
-        mText = new MutableLiveData<>();
-        mText.setValue("This is home fragment");
     }
 
-    public LiveData<String> getText() {
-        return mText;
-    }
 
     public MutableLiveData<List<MissionDesc>> getTopMissions() {
         return topMissions;
@@ -32,7 +25,8 @@
         return recommendMissions;
     }
 
-    public void onRefresh(){
+    @Override
+    public void onRefresh() {
         List<MissionDesc> list = topMissions.getValue() == null? new ArrayList<>() :topMissions.getValue();
         list.clear();
         list.add(new MissionDesc());
@@ -46,6 +40,7 @@
         recommendMissions.setValue(list2);
     }
 
+    @Override
     public void onLoadMore(){
         List<MissionDesc> list = recommendMissions.getValue() == null? new ArrayList<>():recommendMissions.getValue() ;
         list.add(new MissionDesc());
diff --git a/app/src/main/java/com/duqing/missions/ui/main/mine/MineFragment.java b/app/src/main/java/com/duqing/missions/ui/main/mine/MineFragment.java
index 88e886b..3eb8f5e 100644
--- a/app/src/main/java/com/duqing/missions/ui/main/mine/MineFragment.java
+++ b/app/src/main/java/com/duqing/missions/ui/main/mine/MineFragment.java
@@ -4,18 +4,17 @@
 import androidx.lifecycle.Observer;
 import androidx.lifecycle.ViewModelProvider;
 
-import com.duqing.missions.base.BaseFragment;
+import com.duqing.missions.base.fragments.BaseFragment;
 import com.duqing.missions.databinding.FragmentMineBinding;
 
-public class MineFragment extends BaseFragment<FragmentMineBinding> {
+public class MineFragment extends BaseFragment<FragmentMineBinding,MineViewModel> {
 
-    private MineViewModel notificationsViewModel;
 
 
     @Override
     public void initViews() {
-        notificationsViewModel = new ViewModelProvider(this).get(MineViewModel.class);
-        notificationsViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() {
+        viewModel = new ViewModelProvider(this).get(MineViewModel.class);
+        viewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() {
             @Override
             public void onChanged(@Nullable String s) {
             }
diff --git a/app/src/main/res/layout/fragment_hall.xml b/app/src/main/res/layout/fragment_hall.xml
index de2e2f9..433a3f7 100644
--- a/app/src/main/res/layout/fragment_hall.xml
+++ b/app/src/main/res/layout/fragment_hall.xml
@@ -8,7 +8,7 @@
     tools:context=".ui.main.hall.HallFragment" >
 
     <com.google.android.material.tabs.TabLayout
-        android:id="@+id/tablayout"
+        android:id="@+id/tabLayout"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:background="@color/red"
@@ -26,7 +26,7 @@
         android:layout_width="match_parent"
         android:layout_height="0dp"
         android:nestedScrollingEnabled="false"
-        app:layout_constraintTop_toBottomOf="@id/tablayout"
+        app:layout_constraintTop_toBottomOf="@id/tabLayout"
         app:layout_constraintLeft_toLeftOf="parent"
         app:layout_constraintRight_toRightOf="parent"
         app:layout_constraintBottom_toBottomOf="parent" />
diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml
index 3ad528c..60925d1 100644
--- a/app/src/main/res/layout/fragment_home.xml
+++ b/app/src/main/res/layout/fragment_home.xml
@@ -153,7 +153,7 @@
                     android:textColor="@color/black"
                     android:layout_margin="@dimen/activity_horizontal_margin" />
                 <androidx.recyclerview.widget.RecyclerView
-                    android:id="@+id/recycler_recommend"
+                    android:id="@+id/recycler"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:overScrollMode="never"
diff --git a/app/src/main/res/layout/layout_tab_viewpager.xml b/app/src/main/res/layout/layout_tab_viewpager.xml
new file mode 100644
index 0000000..d32546a
--- /dev/null
+++ b/app/src/main/res/layout/layout_tab_viewpager.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout
+    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=".ui.main.hall.HallFragment" >
+
+    <com.google.android.material.tabs.TabLayout
+        android:id="@+id/tabLayout"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        app:tabMaxWidth="0dp"
+        app:tabIndicatorFullWidth="false"
+        app:tabSelectedTextColor="@color/white"
+        app:tabTextColor="@color/enable"
+        app:tabIndicatorColor="@color/white"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <androidx.viewpager2.widget.ViewPager2
+        android:id="@+id/view_pager_2"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:nestedScrollingEnabled="false"
+        app:layout_constraintTop_toBottomOf="@id/tabLayout"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent" />
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file

--
Gitblit v1.9.1