From 298f6750290f7f417f4b47023b1231e11e8a946a Mon Sep 17 00:00:00 2001 From: Dboy <894230813@qq.com> Date: Thu, 8 Jul 2021 09:21:58 +0800 Subject: [PATCH] =?UTF-8?q?Modify:=E5=A2=9E=E5=8A=A0fragment=EF=BC=8Cactiv?= =?UTF-8?q?ity=E9=87=8D=E5=BB=BA=E5=88=A4=E6=96=AD=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0fragment=E9=87=8D=E5=BB=BA=E7=A4=BA=E4=BE=8B=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../base/mvvm/v/BaseFrameActivity.kt | 26 ++++++++ .../base/mvvm/v/BaseFrameFragment.kt | 29 +++++++++ .../base/mvvm/v/FrameView.kt | 7 ++- .../base/utils/ViewRecreateHelper.kt | 42 +++++++++++++ .../net/NetBaseUrlConstant.kt | 8 ++- module_home/src/main/AndroidManifest.xml | 1 + .../com/quyunshuo/module/home/MainActivity.kt | 10 ++- .../home/activity/InternalPagerActivity.kt | 46 ++++++++++++++ .../module/home/fragment/InternalFragment.kt | 48 ++++++++++++++ .../home/fragment/InternalRepository.kt | 18 ++++++ .../module/home/fragment/InternalViewModel.kt | 62 +++++++++++++++++++ .../layout/home_activity_internal_layout.xml | 12 ++++ .../main/res/layout/home_activity_main.xml | 14 +++++ .../layout/home_fragment_internal_layout.xml | 37 +++++++++++ 14 files changed, 357 insertions(+), 3 deletions(-) create mode 100644 lib_base/src/main/java/com/quyunshuo/androidbaseframemvvm/base/utils/ViewRecreateHelper.kt create mode 100644 module_home/src/main/java/com/quyunshuo/module/home/activity/InternalPagerActivity.kt create mode 100644 module_home/src/main/java/com/quyunshuo/module/home/fragment/InternalFragment.kt create mode 100644 module_home/src/main/java/com/quyunshuo/module/home/fragment/InternalRepository.kt create mode 100644 module_home/src/main/java/com/quyunshuo/module/home/fragment/InternalViewModel.kt create mode 100644 module_home/src/main/res/layout/home_activity_internal_layout.xml create mode 100644 module_home/src/main/res/layout/home_fragment_internal_layout.xml diff --git a/lib_base/src/main/java/com/quyunshuo/androidbaseframemvvm/base/mvvm/v/BaseFrameActivity.kt b/lib_base/src/main/java/com/quyunshuo/androidbaseframemvvm/base/mvvm/v/BaseFrameActivity.kt index 6a4217c..2367d1f 100644 --- a/lib_base/src/main/java/com/quyunshuo/androidbaseframemvvm/base/mvvm/v/BaseFrameActivity.kt +++ b/lib_base/src/main/java/com/quyunshuo/androidbaseframemvvm/base/mvvm/v/BaseFrameActivity.kt @@ -7,6 +7,7 @@ import com.alibaba.android.arouter.launcher.ARouter import com.quyunshuo.androidbaseframemvvm.base.utils.BindingReflex import com.quyunshuo.androidbaseframemvvm.base.utils.EventBusRegister import com.quyunshuo.androidbaseframemvvm.base.utils.EventBusUtils +import com.quyunshuo.androidbaseframemvvm.base.utils.ViewRecreateHelper /** * Activity基类 @@ -20,9 +21,16 @@ abstract class BaseFrameActivity : AppCompatActivity(), FrameV BindingReflex.reflexViewBinding(javaClass, layoutInflater) } + /** + * activity页面重建帮助类 + */ + private var mStatusHelper: ActivityRecreateHelper? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(mBinding.root) + //处理保存的装填 + mStatusHelper?.onRestoreInstanceStatus(savedInstanceState) // ARouter 依赖注入 ARouter.getInstance().inject(this) // 注册EventBus @@ -38,4 +46,22 @@ abstract class BaseFrameActivity : AppCompatActivity(), FrameV ) super.onDestroy() } + + override fun isRecreate(): Boolean = mStatusHelper?.isRecreate ?: false + + override fun onSaveInstanceState(outState: Bundle) { + if (mStatusHelper == null) { + //仅当触发重建需要保存状态时创建对象 + mStatusHelper = ActivityRecreateHelper(outState) + } else { + mStatusHelper?.onSaveInstanceState(outState) + } + super.onSaveInstanceState(outState) + } + + /** + * - activity 重建帮助工具类 + */ + private class ActivityRecreateHelper(savedInstanceState: Bundle? = null) : ViewRecreateHelper(savedInstanceState) + } \ No newline at end of file diff --git a/lib_base/src/main/java/com/quyunshuo/androidbaseframemvvm/base/mvvm/v/BaseFrameFragment.kt b/lib_base/src/main/java/com/quyunshuo/androidbaseframemvvm/base/mvvm/v/BaseFrameFragment.kt index a8c1100..0e70caf 100644 --- a/lib_base/src/main/java/com/quyunshuo/androidbaseframemvvm/base/mvvm/v/BaseFrameFragment.kt +++ b/lib_base/src/main/java/com/quyunshuo/androidbaseframemvvm/base/mvvm/v/BaseFrameFragment.kt @@ -10,6 +10,7 @@ import com.alibaba.android.arouter.launcher.ARouter import com.quyunshuo.androidbaseframemvvm.base.utils.BindingReflex import com.quyunshuo.androidbaseframemvvm.base.utils.EventBusRegister import com.quyunshuo.androidbaseframemvvm.base.utils.EventBusUtils +import com.quyunshuo.androidbaseframemvvm.base.utils.ViewRecreateHelper /** * Fragment基类 @@ -23,6 +24,11 @@ abstract class BaseFrameFragment : Fragment(), FrameView { BindingReflex.reflexViewBinding(javaClass, layoutInflater) } + /** + * fragment状态保存工具类 + */ + private var mStatusHelper: FragmentStatusHelper? = null + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -33,6 +39,8 @@ abstract class BaseFrameFragment : Fragment(), FrameView { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + //处理恢复 + mStatusHelper?.onRestoreInstanceStatus(savedInstanceState) // ARouter 依赖注入 ARouter.getInstance().inject(this) // 注册EventBus @@ -42,10 +50,31 @@ abstract class BaseFrameFragment : Fragment(), FrameView { initRequestData() } + override fun isRecreate(): Boolean = mStatusHelper?.isRecreate ?: false + + /** + * 页面可能重建的时候回执行此方法,进行当前页面状态保存 + */ + override fun onSaveInstanceState(outState: Bundle) { + if (mStatusHelper == null) { + //仅当触发重建需要保存状态时创建对象 + mStatusHelper = FragmentStatusHelper(outState) + } else { + mStatusHelper?.onSaveInstanceState(outState) + } + super.onSaveInstanceState(outState) + } + override fun onDestroy() { if (javaClass.isAnnotationPresent(EventBusRegister::class.java)) EventBusUtils.unRegister( this ) super.onDestroy() } + + /** + * - fragment状态保存帮助类; + * - 暂时没有其他需要保存的--空继承 + */ + private class FragmentStatusHelper(savedInstanceState: Bundle? = null) : ViewRecreateHelper(savedInstanceState) } \ No newline at end of file diff --git a/lib_base/src/main/java/com/quyunshuo/androidbaseframemvvm/base/mvvm/v/FrameView.kt b/lib_base/src/main/java/com/quyunshuo/androidbaseframemvvm/base/mvvm/v/FrameView.kt index 9c938e2..434edf5 100644 --- a/lib_base/src/main/java/com/quyunshuo/androidbaseframemvvm/base/mvvm/v/FrameView.kt +++ b/lib_base/src/main/java/com/quyunshuo/androidbaseframemvvm/base/mvvm/v/FrameView.kt @@ -20,7 +20,12 @@ interface FrameView { fun initLiveDataObserve() /** - * 初始化界面创建时的数据请求 + * 初始化界面创建时的数据请求,尝试在此方法内调用[isRecreate]进行重建判断,防止数据重复获取 */ fun initRequestData() + + /** + * 页面是否重建,fragment被回收重新展示的时候为true,系统环境发生变化activity重新创建时为true + */ + fun isRecreate(): Boolean } \ No newline at end of file diff --git a/lib_base/src/main/java/com/quyunshuo/androidbaseframemvvm/base/utils/ViewRecreateHelper.kt b/lib_base/src/main/java/com/quyunshuo/androidbaseframemvvm/base/utils/ViewRecreateHelper.kt new file mode 100644 index 0000000..562ef69 --- /dev/null +++ b/lib_base/src/main/java/com/quyunshuo/androidbaseframemvvm/base/utils/ViewRecreateHelper.kt @@ -0,0 +1,42 @@ +package com.quyunshuo.androidbaseframemvvm.base.utils + +import android.os.Bundle + +/** + * @author DBoy 2021/7/8 + * + * - 文件描述 : 视图,activity,fragment重建帮助类 + */ +open class ViewRecreateHelper(savedInstanceState: Bundle?=null) { + /** + * 重建标记key + */ + private val KEY_RECREATE = "recreate" + + /** + * 是否重建 + */ + var isRecreate = false + private set + + init { + if (savedInstanceState!=null) { + this.onSaveInstanceState(savedInstanceState) + } + } + + /** + * 恢复状态 + */ + open fun onRestoreInstanceStatus(savedInstanceState: Bundle?) { + isRecreate = savedInstanceState?.getBoolean(KEY_RECREATE) ?: false + } + + /** + * 保存状态 + */ + open fun onSaveInstanceState(bundle: Bundle) { + bundle.putBoolean(KEY_RECREATE, true) + } + +} \ No newline at end of file diff --git a/lib_net/src/main/java/com/quyunshuo/androidbaseframemvvm/net/NetBaseUrlConstant.kt b/lib_net/src/main/java/com/quyunshuo/androidbaseframemvvm/net/NetBaseUrlConstant.kt index bed1a55..19d74de 100644 --- a/lib_net/src/main/java/com/quyunshuo/androidbaseframemvvm/net/NetBaseUrlConstant.kt +++ b/lib_net/src/main/java/com/quyunshuo/androidbaseframemvvm/net/NetBaseUrlConstant.kt @@ -8,5 +8,11 @@ package com.quyunshuo.androidbaseframemvvm.net */ internal object NetBaseUrlConstant { - const val MAIN_URL = "" + val MAIN_URL = "https://www.baidu.com" + get() { + if (field.isEmpty()){ + throw NotImplementedError("请求改你的 MAIN_URL 的值为自己的请求地址") + } + return field + } } \ No newline at end of file diff --git a/module_home/src/main/AndroidManifest.xml b/module_home/src/main/AndroidManifest.xml index d9e29be..61f6e29 100644 --- a/module_home/src/main/AndroidManifest.xml +++ b/module_home/src/main/AndroidManifest.xml @@ -11,6 +11,7 @@ + \ No newline at end of file diff --git a/module_home/src/main/java/com/quyunshuo/module/home/MainActivity.kt b/module_home/src/main/java/com/quyunshuo/module/home/MainActivity.kt index 69ccbe2..80f8127 100644 --- a/module_home/src/main/java/com/quyunshuo/module/home/MainActivity.kt +++ b/module_home/src/main/java/com/quyunshuo/module/home/MainActivity.kt @@ -1,9 +1,12 @@ package com.quyunshuo.module.home +import android.content.Intent import android.graphics.Color import androidx.activity.viewModels import com.quyunshuo.androidbaseframemvvm.common.ui.BaseActivity +import com.quyunshuo.module.home.activity.InternalPagerActivity import com.quyunshuo.module.home.databinding.HomeActivityMainBinding +import com.quyunshuo.module.home.fragment.InternalFragment import dagger.hilt.android.AndroidEntryPoint /** @@ -20,9 +23,14 @@ class MainActivity : BaseActivity() { */ private val mViewModel by viewModels() - override fun HomeActivityMainBinding.initView() {} + override fun HomeActivityMainBinding.initView() { + goToNextBtn.setOnClickListener { + startActivity(Intent(this@MainActivity, InternalPagerActivity::class.java)) + } + } override fun initLiveDataObserve() { + // 订阅数据 mViewModel.data.observe(this, { mBinding.vTvHello.text = it diff --git a/module_home/src/main/java/com/quyunshuo/module/home/activity/InternalPagerActivity.kt b/module_home/src/main/java/com/quyunshuo/module/home/activity/InternalPagerActivity.kt new file mode 100644 index 0000000..000c66f --- /dev/null +++ b/module_home/src/main/java/com/quyunshuo/module/home/activity/InternalPagerActivity.kt @@ -0,0 +1,46 @@ +package com.quyunshuo.module.home.activity + +import androidx.fragment.app.Fragment +import androidx.viewpager2.adapter.FragmentStateAdapter +import com.quyunshuo.androidbaseframemvvm.common.ui.BaseActivity +import com.quyunshuo.module.home.databinding.HomeActivityInternalLayoutBinding +import com.quyunshuo.module.home.fragment.InternalFragment +import dagger.hilt.android.AndroidEntryPoint + +/** + * @author DBoy 2021/7/6

+ * - 文件描述 : ViewPager2+fragment 模拟Fragment页面重建。 + */ +@AndroidEntryPoint +class InternalPagerActivity : BaseActivity() { + + override fun HomeActivityInternalLayoutBinding.initView() { + initPager() + } + + private fun initPager() { + val fragments = mutableListOf( + InternalFragment(), + InternalFragment(), + InternalFragment(), + InternalFragment(), + InternalFragment(), + InternalFragment(), + InternalFragment() + ) + mBinding.viewPager.adapter = object : FragmentStateAdapter(this) { + override fun getItemCount(): Int = fragments.size + override fun createFragment(position: Int): Fragment = fragments[position] + } + + } + + override fun initLiveDataObserve() { + + } + + override fun initRequestData() { + + } + +} \ No newline at end of file diff --git a/module_home/src/main/java/com/quyunshuo/module/home/fragment/InternalFragment.kt b/module_home/src/main/java/com/quyunshuo/module/home/fragment/InternalFragment.kt new file mode 100644 index 0000000..c240187 --- /dev/null +++ b/module_home/src/main/java/com/quyunshuo/module/home/fragment/InternalFragment.kt @@ -0,0 +1,48 @@ +package com.quyunshuo.module.home.fragment + +import androidx.fragment.app.viewModels +import com.quyunshuo.androidbaseframemvvm.common.ui.BaseFragment +import com.quyunshuo.module.home.databinding.HomeFragmentInternalLayoutBinding +import dagger.hilt.android.AndroidEntryPoint + +/** + * @author DBoy 2021/7/6

+ * - 文件描述 : 测试fragment + */ +@AndroidEntryPoint +class InternalFragment : BaseFragment() { + + private val mViewModel by viewModels() + + override fun HomeFragmentInternalLayoutBinding.initView() { + + } + + override fun initLiveDataObserve() { + mViewModel.recreatedCont.observe(viewLifecycleOwner) { + mBinding.recreateContTv.text = "重建次数 $it" + } + mViewModel.firstData.observe(viewLifecycleOwner) { + mBinding.loadDataTv.text = it + } + mViewModel.isLoading.observe(viewLifecycleOwner) { + mBinding.loadingStatusTv.text = if (it) { + "正在加载..." + } else { + "加载完成!" + } + } + } + + override fun initRequestData() { + //每次重建都会累加数据 + mViewModel.increase() + //当页面重建的时候不再重新请求数据,且当前页面数据数据有且没有刷新逻辑的情况下不再请求数据。 + if (isRecreate() && mViewModel.firstData.value != null) { + return + } + mViewModel.getData() + } + + +} \ No newline at end of file diff --git a/module_home/src/main/java/com/quyunshuo/module/home/fragment/InternalRepository.kt b/module_home/src/main/java/com/quyunshuo/module/home/fragment/InternalRepository.kt new file mode 100644 index 0000000..d970cbd --- /dev/null +++ b/module_home/src/main/java/com/quyunshuo/module/home/fragment/InternalRepository.kt @@ -0,0 +1,18 @@ +package com.quyunshuo.module.home.fragment + +import com.quyunshuo.androidbaseframemvvm.base.mvvm.m.BaseRepository +import kotlinx.coroutines.delay +import javax.inject.Inject + +/** + * @author DBoy 2021/7/6

+ * - 文件描述 : + */ +class InternalRepository @Inject constructor() : BaseRepository() { + + suspend fun getData() = flowRequest { + delay(1000) + emit("数据加载成功") + } + +} \ No newline at end of file diff --git a/module_home/src/main/java/com/quyunshuo/module/home/fragment/InternalViewModel.kt b/module_home/src/main/java/com/quyunshuo/module/home/fragment/InternalViewModel.kt new file mode 100644 index 0000000..4150afb --- /dev/null +++ b/module_home/src/main/java/com/quyunshuo/module/home/fragment/InternalViewModel.kt @@ -0,0 +1,62 @@ +package com.quyunshuo.module.home.fragment + +import android.util.Log +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.viewModelScope +import com.quyunshuo.androidbaseframemvvm.base.mvvm.vm.BaseViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.launch +import javax.inject.Inject + +/** + * @author DBoy 2021/7/6

+ * - 文件描述 : + */ +@HiltViewModel +class InternalViewModel @Inject constructor(private val repository: InternalRepository) : BaseViewModel() { + + /** + * 重建计数 + */ + val recreatedCont = MutableLiveData() + + /** + * 首个数据 + */ + val firstData = MutableLiveData() + + /** + * 累加重建次数 + */ + fun increase() { + val value = recreatedCont.value ?: 0 + recreatedCont.value = value + 1 + } + + /** + * 获取数据 + */ + fun getData() { + isLoading.value = true + viewModelScope.launch(Dispatchers.IO) { + repository.getData() + .catch { + Log.d("DJC", "getData: ") + }.collect { + isLoading.postValue(false) + delay(200) + firstData.postValue(it) + } + } + } + + override fun onCleared() { + super.onCleared() + Log.d("DJC","InternalViewModel Clear") + } + +} diff --git a/module_home/src/main/res/layout/home_activity_internal_layout.xml b/module_home/src/main/res/layout/home_activity_internal_layout.xml new file mode 100644 index 0000000..ad24de9 --- /dev/null +++ b/module_home/src/main/res/layout/home_activity_internal_layout.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/module_home/src/main/res/layout/home_activity_main.xml b/module_home/src/main/res/layout/home_activity_main.xml index 3ecbc1c..2437467 100644 --- a/module_home/src/main/res/layout/home_activity_main.xml +++ b/module_home/src/main/res/layout/home_activity_main.xml @@ -20,4 +20,18 @@ app:layout_constraintTop_toTopOf="parent" tools:ignore="HardcodedText" /> +