refactor(frame): 优化框架

- 添加和优化扩展方法
- 优化屏幕适配兼容性问题
This commit is contained in:
Quyunshuo
2021-09-26 22:18:41 +08:00
parent 4b705ef9c2
commit 086078f618
16 changed files with 325 additions and 343 deletions

View File

@@ -11,7 +11,6 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".activity.InternalPagerActivity" />
</application>
</manifest>

View File

@@ -2,13 +2,11 @@ package com.quyunshuo.module.home.activity
import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.quyunshuo.androidbaseframemvvm.base.ktx.launchIO
import com.quyunshuo.androidbaseframemvvm.base.mvvm.vm.BaseViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import javax.inject.Inject
/**
@@ -28,7 +26,7 @@ class HomeViewModel @Inject constructor(private val mRepository: HomeRepository)
* 模拟获取数据
*/
fun getData() {
viewModelScope.launch(Dispatchers.IO) {
launchIO {
mRepository.getData()
.catch { Log.d("qqq", "getData: $it") }
.collect { data.postValue(it) }

View File

@@ -1,93 +1,93 @@
package com.quyunshuo.module.home.activity
import android.os.Bundle
import androidx.activity.viewModels
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.quyunshuo.androidbaseframemvvm.base.mvvm.vm.EmptyViewModel
import com.quyunshuo.androidbaseframemvvm.common.ui.BaseActivity
import com.quyunshuo.androidbaseframemvvm.common.ui.BaseFragmentStateAdapter
import com.quyunshuo.module.home.databinding.HomeActivityInternalLayoutBinding
import com.quyunshuo.module.home.fragment.InternalFragment
import dagger.hilt.android.AndroidEntryPoint
import kotlin.random.Random
/**
* @author DBoy 2021/7/6 <p>
* - 文件描述 : ViewPager2+fragment 模拟Fragment页面重建。
*/
@AndroidEntryPoint
class InternalPagerActivity : BaseActivity<HomeActivityInternalLayoutBinding, EmptyViewModel>() {
override val mViewModel: EmptyViewModel by viewModels()
private val mCreateFragmentData = mutableListOf<String>()
private var mAdapter: InternalPagerFragmentAdapter? = null
override fun HomeActivityInternalLayoutBinding.initView() {
addFragment.setOnClickListener {
//添加一个随机页面
mAdapter?.addData("Pager ID:${Random.nextInt()}")
}
removeFragment.setOnClickListener {
//移除当前展示页面
// mAdapter?.removeData("更多")
mAdapter?.removeData(viewPager.currentItem)
}
initPager()
}
private fun initPager() {
mCreateFragmentData.add("首页")
mCreateFragmentData.add("我的")
mCreateFragmentData.add("设置")
mCreateFragmentData.add("更多")
mCreateFragmentData.add("动态")
mAdapter = InternalPagerFragmentAdapter(this, mCreateFragmentData)
mBinding.viewPager.adapter = mAdapter
}
override fun initObserve() {}
override fun initRequestData() {}
class InternalPagerFragmentAdapter(activity: FragmentActivity, data: MutableList<String> = mutableListOf()) :
BaseFragmentStateAdapter<String>(activity, data) {
override fun createFragment(item: String, position: Int): Fragment {
val bundle = Bundle().apply {
putString("What", item)
}
return when (item) {
"首页" -> {
//假装首页
InternalFragment()
}
"我的" -> {
//假装我的
InternalFragment()
}
"设置" -> {
//假装设置
InternalFragment()
}
"更多" -> {
//假装更多
InternalFragment()
}
else -> {
//另外动态item创建类型
InternalFragment()
}
}.apply {
//设置传递参数bundle
arguments = bundle
}
}
}
}
//package com.quyunshuo.module.home.activity
//
//import android.os.Bundle
//import androidx.activity.viewModels
//import androidx.fragment.app.Fragment
//import androidx.fragment.app.FragmentActivity
//import com.quyunshuo.androidbaseframemvvm.base.mvvm.vm.EmptyViewModel
//import com.quyunshuo.androidbaseframemvvm.common.ui.BaseActivity
//import com.quyunshuo.androidbaseframemvvm.common.ui.BaseFragmentStateAdapter
//import com.quyunshuo.module.home.databinding.HomeActivityInternalLayoutBinding
//import com.quyunshuo.module.home.fragment.InternalFragment
//import dagger.hilt.android.AndroidEntryPoint
//import kotlin.random.Random
//
///**
// * @author DBoy 2021/7/6 <p>
// * - 文件描述 : ViewPager2+fragment 模拟Fragment页面重建。
// */
//@AndroidEntryPoint
//class InternalPagerActivity : BaseActivity<HomeActivityInternalLayoutBinding, EmptyViewModel>() {
//
// override val mViewModel: EmptyViewModel by viewModels()
//
// private val mCreateFragmentData = mutableListOf<String>()
//
// private var mAdapter: InternalPagerFragmentAdapter? = null
//
//
// override fun HomeActivityInternalLayoutBinding.initView() {
// addFragment.setOnClickListener {
// //添加一个随机页面
// mAdapter?.addData("Pager ID:${Random.nextInt()}")
// }
// removeFragment.setOnClickListener {
// //移除当前展示页面
//// mAdapter?.removeData("更多")
// mAdapter?.removeData(viewPager.currentItem)
// }
// initPager()
// }
//
// private fun initPager() {
// mCreateFragmentData.add("首页")
// mCreateFragmentData.add("我的")
// mCreateFragmentData.add("设置")
// mCreateFragmentData.add("更多")
// mCreateFragmentData.add("动态")
// mAdapter = InternalPagerFragmentAdapter(this, mCreateFragmentData)
// mBinding.viewPager.adapter = mAdapter
//
// }
//
// override fun initObserve() {}
//
// override fun initRequestData() {}
//
// class InternalPagerFragmentAdapter(activity: FragmentActivity, data: MutableList<String> = mutableListOf()) :
// BaseFragmentStateAdapter<String>(activity, data) {
// override fun createFragment(item: String, position: Int): Fragment {
// val bundle = Bundle().apply {
// putString("What", item)
// }
// return when (item) {
// "首页" -> {
// //假装首页
// InternalFragment()
// }
// "我的" -> {
// //假装我的
// InternalFragment()
// }
// "设置" -> {
// //假装设置
// InternalFragment()
// }
// "更多" -> {
// //假装更多
// InternalFragment()
// }
// else -> {
// //另外动态item创建类型
// InternalFragment()
// }
// }.apply {
// //设置传递参数bundle
// arguments = bundle
// }
// }
//
//
// }
//
//}

View File

@@ -1,8 +1,8 @@
package com.quyunshuo.module.home.activity
import android.content.Intent
import android.graphics.Color
import androidx.activity.viewModels
import com.quyunshuo.androidbaseframemvvm.base.ktx.observeLiveData
import com.quyunshuo.androidbaseframemvvm.common.ui.BaseActivity
import com.quyunshuo.module.home.databinding.HomeActivityMainBinding
import dagger.hilt.android.AndroidEntryPoint
@@ -21,18 +21,15 @@ class MainActivity : BaseActivity<HomeActivityMainBinding, HomeViewModel>() {
*/
override val mViewModel by viewModels<HomeViewModel>()
override fun HomeActivityMainBinding.initView() {
goToNextBtn.setOnClickListener {
startActivity(Intent(this@MainActivity, InternalPagerActivity::class.java))
}
}
override fun HomeActivityMainBinding.initView() {}
override fun initObserve() {
// 订阅数据
mViewModel.data.observe(this, {
mBinding.vTvHello.text = it
mBinding.vTvHello.setTextColor(Color.BLUE)
})
observeLiveData(mViewModel.data, ::processData)
}
private fun processData(data: String) {
mBinding.vTvHello.text = data
mBinding.vTvHello.setTextColor(Color.BLUE)
}
override fun initRequestData() {

View File

@@ -1,85 +1,85 @@
package com.quyunshuo.module.home.fragment
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.viewModels
import com.quyunshuo.androidbaseframemvvm.base.utils.status.ViewStatusHelper
import com.quyunshuo.androidbaseframemvvm.common.ui.BaseFragment
import com.quyunshuo.module.home.databinding.HomeFragmentInternalLayoutBinding
import dagger.hilt.android.AndroidEntryPoint
/**
* @author DBoy 2021/7/6 <p>
* - 文件描述 : 测试fragment
*/
@AndroidEntryPoint
class InternalFragment : BaseFragment<HomeFragmentInternalLayoutBinding, InternalViewModel>() {
override val mViewModel by viewModels<InternalViewModel>()
/**
* 页面状态数据管理帮助类
*/
private lateinit var mInternalFragmentStatusHelper: InternalFragmentStatusHelper
/***
* 注册帮助类
*/
override fun onRegisterStatusHelper(): ViewStatusHelper? {
mInternalFragmentStatusHelper = InternalFragmentStatusHelper(super.onRegisterStatusHelper())
return mInternalFragmentStatusHelper
}
override fun HomeFragmentInternalLayoutBinding.initView() {}
override fun initObserve() {
mViewModel.increase(mInternalFragmentStatusHelper.rebuildSize)
val s = arguments?.getString("What") ?: ""
mBinding.toolBarTitle.text = s
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 {
// "加载完成!"
// }
//package com.quyunshuo.module.home.fragment
//
//import android.os.Bundle
//import android.util.Log
//import androidx.fragment.app.viewModels
//import com.quyunshuo.androidbaseframemvvm.base.utils.status.ViewStatusHelper
//import com.quyunshuo.androidbaseframemvvm.common.ui.BaseFragment
//import com.quyunshuo.module.home.databinding.HomeFragmentInternalLayoutBinding
//import dagger.hilt.android.AndroidEntryPoint
//
///**
// * @author DBoy 2021/7/6 <p>
// * - 文件描述 : 测试fragment
// */
//@AndroidEntryPoint
//class InternalFragment : BaseFragment<HomeFragmentInternalLayoutBinding, InternalViewModel>() {
//
// override val mViewModel by viewModels<InternalViewModel>()
//
// /**
// * 页面状态数据管理帮助类
// */
// private lateinit var mInternalFragmentStatusHelper: InternalFragmentStatusHelper
//
// /***
// * 注册帮助类
// */
// override fun onRegisterStatusHelper(): ViewStatusHelper? {
// mInternalFragmentStatusHelper = InternalFragmentStatusHelper(super.onRegisterStatusHelper())
// return mInternalFragmentStatusHelper
// }
//
// override fun HomeFragmentInternalLayoutBinding.initView() {}
//
//
// override fun initObserve() {
// mViewModel.increase(mInternalFragmentStatusHelper.rebuildSize)
// val s = arguments?.getString("What") ?: ""
// mBinding.toolBarTitle.text = s
// mViewModel.recreatedCont.observe(viewLifecycleOwner) {
// mBinding.recreateContTv.text = "重建次数 $it"
// }
}
override fun initRequestData() {
//当页面重建的时候不再重新请求数据,且当前页面数据数据有且没有刷新逻辑的情况下不再请求数据。
if (isRecreate() && mViewModel.firstData.value != null) {
return
}
mViewModel.getData()
}
/**
* 当前Fragment重建帮助类
*/
internal class InternalFragmentStatusHelper(parentViewStatusHelper: ViewStatusHelper?) : ViewStatusHelper(parentViewStatusHelper) {
/**
* 重建次数
*/
var rebuildSize = 0
private val KEY_REBUILD = "com.quyunshuo.module.home.fragment.InternalFragment.InternalFragmentStatusHelper.rebuild"
override fun onRestoreInstanceStatus(savedInstanceState: Bundle?) {
super.onRestoreInstanceStatus(savedInstanceState)
rebuildSize = (savedInstanceState?.getInt(KEY_REBUILD) ?: 0) + 1
}
override fun onSaveInstanceState(bundle: Bundle) {
super.onSaveInstanceState(bundle)
bundle.putInt(KEY_REBUILD, rebuildSize)
}
}
}
// mViewModel.firstData.observe(viewLifecycleOwner) {
// mBinding.loadDataTv.text = it
// }
//// mViewModel.isLoading.observe(viewLifecycleOwner) {
//// mBinding.loadingStatusTv.text = if (it) {
//// "正在加载..."
//// } else {
//// "加载完成!"
//// }
//// }
// }
//
// override fun initRequestData() {
// //当页面重建的时候不再重新请求数据,且当前页面数据数据有且没有刷新逻辑的情况下不再请求数据。
// if (isRecreate() && mViewModel.firstData.value != null) {
// return
// }
// mViewModel.getData()
// }
//
// /**
// * 当前Fragment重建帮助类
// */
// internal class InternalFragmentStatusHelper(parentViewStatusHelper: ViewStatusHelper?) : ViewStatusHelper(parentViewStatusHelper) {
// /**
// * 重建次数
// */
// var rebuildSize = 0
//
// private val KEY_REBUILD = "com.quyunshuo.module.home.fragment.InternalFragment.InternalFragmentStatusHelper.rebuild"
//
// override fun onRestoreInstanceStatus(savedInstanceState: Bundle?) {
// super.onRestoreInstanceStatus(savedInstanceState)
// rebuildSize = (savedInstanceState?.getInt(KEY_REBUILD) ?: 0) + 1
// }
//
// override fun onSaveInstanceState(bundle: Bundle) {
// super.onSaveInstanceState(bundle)
// bundle.putInt(KEY_REBUILD, rebuildSize)
// }
// }
//
//}

View File

@@ -1,17 +1,17 @@
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 <p>
* - 文件描述 :
*/
class InternalRepository @Inject constructor() : BaseRepository() {
suspend fun getData() = request<String> {
delay(1000)
emit("数据加载成功")
}
}
//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 <p>
// * - 文件描述 :
// */
//class InternalRepository @Inject constructor() : BaseRepository() {
//
// suspend fun getData() = request<String> {
// delay(1000)
// emit("数据加载成功")
// }
//}

View File

@@ -1,65 +1,65 @@
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 com.quyunshuo.androidbaseframemvvm.base.utils.status.ViewStatusHelper
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.flow.onStart
import kotlinx.coroutines.launch
import javax.inject.Inject
/**
* @author DBoy 2021/7/6 <p>
* - 文件描述 : ViewModel再ViewPager2的Fragment中会随着Fragment执行[Fragment.onDestory]一同销毁。
* 所以一些需要长期保存的变量数据不适合保存再ViewModel考虑使用[ViewStatusHelper]保存页面上部分数据,
* 页面恢复的时候再交给ViewModel处理,例如[recreatedCont]
*/
@HiltViewModel
class InternalViewModel @Inject constructor() :
BaseViewModel() {
@Inject
lateinit var repository: InternalRepository
/**
* 重建计数
*/
val recreatedCont = MutableLiveData<Int>()
/**
* 首个数据
*/
val firstData = MutableLiveData<String>()
/**
* 累加重建次数
*/
fun increase(size: Int) {
recreatedCont.value = size
}
/**
* 获取数据
*/
fun getData() {
viewModelScope.launch(Dispatchers.IO) {
repository.getData()
.catch {
Log.d("DJC", "getData: ")
}
.onStart { changeStateView(loading = true) }
.collect {
changeStateView(hide = true)
delay(200)
firstData.postValue(it)
}
}
}
}
//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 com.quyunshuo.androidbaseframemvvm.base.utils.status.ViewStatusHelper
//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.flow.onStart
//import kotlinx.coroutines.launch
//import javax.inject.Inject
//
///**
// * @author DBoy 2021/7/6 <p>
// * - 文件描述 : ViewModel再ViewPager2的Fragment中会随着Fragment执行[Fragment.onDestory]一同销毁。
// * 所以一些需要长期保存的变量数据不适合保存再ViewModel考虑使用[ViewStatusHelper]保存页面上部分数据,
// * 页面恢复的时候再交给ViewModel处理,例如[recreatedCont]
// */
//@HiltViewModel
//class InternalViewModel @Inject constructor() :
// BaseViewModel() {
//
// @Inject
// lateinit var repository: InternalRepository
//
// /**
// * 重建计数
// */
// val recreatedCont = MutableLiveData<Int>()
//
// /**
// * 首个数据
// */
// val firstData = MutableLiveData<String>()
//
// /**
// * 累加重建次数
// */
// fun increase(size: Int) {
// recreatedCont.value = size
// }
//
// /**
// * 获取数据
// */
// fun getData() {
// viewModelScope.launch(Dispatchers.IO) {
// repository.getData()
// .catch {
// Log.d("DJC", "getData: ")
// }
// .onStart { changeStateView(loading = true) }
// .collect {
// changeStateView(hide = true)
// delay(200)
// firstData.postValue(it)
// }
// }
// }
//
//}

View File

@@ -20,18 +20,4 @@
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<Button
android:id="@+id/goToNextBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:text="进入ViewPager2示例"
android:textAllCaps="false"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/vTvHello"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>