@@ -6,6 +6,7 @@ import android.widget.TextView | |||
import com.suliang.common.base.adapter.BaseAdapterViewHolder | |||
import com.suliang.common.base.adapter.BaseRVAdapter | |||
import com.suliang.common.extension.click | |||
import com.suliang.common.util.LogUtil | |||
import com.suliang.common.util.StringUtil | |||
import com.xkl.cdl.R | |||
import com.xkl.cdl.data.AppConstants | |||
@@ -60,7 +61,7 @@ class AdapterHistoricalRoute(val courseType : Int) : BaseRVAdapter<LearnWord>() | |||
override fun onBindVH(holder : BaseAdapterViewHolder, position : Int) { | |||
when (courseType) { | |||
AppConstants.COURSE_TYPE_ENGLISH_VOICE, | |||
AppConstants.COURSE_TYPE_ENGLISH_SPELL -> bindSpellOrVoice(holder, position) | |||
AppConstants.COURSE_TYPE_ENGLISH_SPELL -> bindSpellOrVoice(holder, holder.adapterPosition) | |||
else -> bindDiscern(holder, position) | |||
} | |||
} | |||
@@ -124,6 +125,7 @@ class AdapterHistoricalRoute(val courseType : Int) : BaseRVAdapter<LearnWord>() | |||
previousIsShowLine = previousSelectPosition == itemCount-1 && !lastIsLearnOver | |||
currentSelectPosition = position | |||
currentIsShowLine = true | |||
LogUtil.e(" root click previousSelectPosition = $previousSelectPosition currentSelectPosition = $currentSelectPosition") | |||
notifyItemChanged(previousSelectPosition) | |||
notifyItemChanged(currentSelectPosition) | |||
//事件 | |||
@@ -162,10 +164,16 @@ class AdapterHistoricalRoute(val courseType : Int) : BaseRVAdapter<LearnWord>() | |||
/** 拼写完成,点击下一条时,按需要调用移除当前item项 */ | |||
fun spellNeedRemoveCurrent(){ | |||
val tempPosition = currentSelectPosition | |||
currentIsShowLine = false | |||
currentSelectPosition = -1 | |||
removeData(tempPosition) | |||
LogUtil.e(" remove item before -> previousSelectPosition = $previousSelectPosition currentSelectPosition = $currentSelectPosition itemCount = $itemCount") | |||
// val tempPosition = currentSelectPosition | |||
// currentIsShowLine = false | |||
// currentSelectPosition = -1 | |||
// 如果上一个位置大于现在的选择位置,则移除当前位置后,坐标改变,上一个选中位置需要减一,否则位置不一致 | |||
if (previousSelectPosition > currentSelectPosition){ | |||
previousSelectPosition-- | |||
} | |||
removeData(currentSelectPosition) | |||
LogUtil.e(" remove item after-> previousSelectPosition = $previousSelectPosition currentSelectPosition = $currentSelectPosition itemCount = $itemCount") | |||
} | |||
@@ -216,14 +216,13 @@ class LearnDialog private constructor() : BaseDialogFragment<DialogLessonLearnBi | |||
private fun initLessonAfterTestOver(){ | |||
initNumber() | |||
initScore() | |||
binding.run { | |||
tvScore.visibility = View.VISIBLE | |||
tvTip.visibility = View.VISIBLE | |||
tvTitle.visibility = View.VISIBLE | |||
tvTip1.visibility = View.VISIBLE | |||
incStatisticsNumber.root.visibility = View.VISIBLE | |||
tvTop.visibility = View.VISIBLE | |||
tvLeft.visibility = View.VISIBLE | |||
vSplit.visibility = View.VISIBLE | |||
tvTitle.text = "恭喜你,完成了课时学后测试" |
@@ -145,7 +145,7 @@ class LearnExamViewModel : LearnBaseViewModel() { | |||
/** 获取下一题数据 */ | |||
fun loadNext() { | |||
LogUtil.e("获取下一题") | |||
// LogUtil.e("获取下一题") | |||
isGetNextIng = true | |||
mHandler.postDelayed(toNextRunable, toNextTime) | |||
} |
@@ -19,7 +19,6 @@ import com.suliang.common.base.activity.BaseActivityVM | |||
import com.suliang.common.extension.click | |||
import com.suliang.common.util.DateUtil | |||
import com.suliang.common.util.DrawableUti | |||
import com.suliang.common.util.LogUtil | |||
import com.suliang.common.util.image.ImageLoader | |||
import com.suliang.common.util.media.EMediaState | |||
import com.suliang.common.util.media.IMPListener | |||
@@ -130,7 +129,12 @@ class LearnWordActivity : BaseActivityVM<ActivityLearnWordBinding, LearnWordView | |||
/** 历史轨迹初始 */ | |||
private fun initHistoricalRoute() { | |||
adapterHistorical = AdapterHistoricalRoute(vm.learnData.lesson.courseType).apply { | |||
val initCourseType = when{ | |||
//自动播放时,将历史轨迹的课时类型修改为单词类型,避免辨音课程自动播放时显示横线 | |||
vm.learnData.isAutoPlay -> AppConstants.COURSE_TYPE_ENGLISH_DISCERN | |||
else -> vm.learnData.lesson.courseType | |||
} | |||
adapterHistorical = AdapterHistoricalRoute(initCourseType).apply { | |||
onItemClick = { v : View, position : Int, item : LearnWord -> | |||
if (!vm.learnData.isAutoPlay) { //自动播放历史轨迹点击无效 | |||
vm.clickHistoricalItem(item) | |||
@@ -156,7 +160,7 @@ class LearnWordActivity : BaseActivityVM<ActivityLearnWordBinding, LearnWordView | |||
bindingSpell.spellRecyclerView.run { | |||
layoutManager = GridLayoutManager(this@LearnWordActivity, 2, GridLayoutManager.HORIZONTAL, false) | |||
addItemDecoration(SpellItemDecoration()) | |||
setHasFixedSize(true) | |||
// setHasFixedSize(true) | |||
(itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false | |||
spellAdapter = AdapterSpell().apply { | |||
onItemSpellingClickListener = itemSpellingClick | |||
@@ -353,8 +357,8 @@ class LearnWordActivity : BaseActivityVM<ActivityLearnWordBinding, LearnWordView | |||
return@observe | |||
} | |||
it?.run { | |||
if (vm.learnData.lesson.courseType == AppConstants.COURSE_TYPE_ENGLISH_VOICE && bindingWord.ivVoice.visibility == View.VISIBLE) MPManager.play( | |||
it, listener = impListener) | |||
if (vm.learnData.lesson.courseType == AppConstants.COURSE_TYPE_ENGLISH_VOICE && bindingWord.ivVoice.visibility == View.VISIBLE) | |||
MPManager.play(it, listener = impListener) | |||
else MPManager.play(it) | |||
} ?: showToast("未找到发音文件") | |||
} | |||
@@ -382,9 +386,15 @@ class LearnWordActivity : BaseActivityVM<ActivityLearnWordBinding, LearnWordView | |||
} | |||
//界面初始 | |||
when (vm.learnData.lesson.courseType) { | |||
AppConstants.COURSE_TYPE_ENGLISH_VOICE -> initVoice(it) | |||
AppConstants.COURSE_TYPE_ENGLISH_VOICE -> { | |||
initVoice(it) | |||
readFirst() | |||
} | |||
AppConstants.COURSE_TYPE_ENGLISH_SPELL -> initSpell(it) | |||
else -> initWord(it) | |||
else -> { | |||
initWord(it) | |||
readFirst() //发音 | |||
} | |||
} | |||
} | |||
@@ -439,8 +449,6 @@ class LearnWordActivity : BaseActivityVM<ActivityLearnWordBinding, LearnWordView | |||
/**新数据到来,进行初始化*/ | |||
@SuppressLint("SetTextI18n") | |||
private fun initWord(learnWord : LearnWord) { | |||
//发音 | |||
readFirst() | |||
//图片 | |||
if (vm.isNeedLoadPhoto) { | |||
bindingWord.imgWord.visibility = View.INVISIBLE | |||
@@ -601,21 +609,17 @@ class LearnWordActivity : BaseActivityVM<ActivityLearnWordBinding, LearnWordView | |||
/** 滑动到最后一项进行点击 */ | |||
private fun skipToHistoricalLastItem() { | |||
val lastPosition = historicalLayoutManager.findLastCompletelyVisibleItemPosition() | |||
val itemCount = historicalLayoutManager.itemCount | |||
LogUtil.e("recyclerView smooth before -> completeVisibleItemPositon = $lastPosition , itemCount = $itemCount") | |||
if (lastPosition == itemCount - 1) { | |||
historicalLayoutManager.findViewByPosition(lastPosition)?.performClick() | |||
} else { | |||
binding.rvHistoricalRoute.addOnScrollListener(historicalScrollListener) | |||
binding.rvHistoricalRoute.smoothScrollToPosition(adapterHistorical.itemCount - 1) | |||
binding.rvHistoricalRoute.post{ | |||
val position = adapterHistorical.itemCount - 1 //最后item的位置 | |||
val last = historicalLayoutManager.findLastCompletelyVisibleItemPosition() //最后完全可见 | |||
if (position > last ){ //需要操作的位置大于当前最后显示的位置,则进行滚动 | |||
binding.rvHistoricalRoute.addOnScrollListener(historicalScrollListener) | |||
binding.rvHistoricalRoute.smoothScrollToPosition(position) | |||
}else { //position view 可见 | |||
historicalLayoutManager.findViewByPosition(position)?.performClick() | |||
} | |||
} | |||
//other way | |||
// historicalLayoutManager.scrollToPositionWithOffset(adapterHistorical.itemCount - 1,0) | |||
// historicalLayoutManager.findViewByPosition(historicalLayoutManager.findLastCompletelyVisibleItemPosition())?.performClick() | |||
} | |||
private val historicalScrollListener = object : OnScrollListener() { | |||
override fun onScrollStateChanged(recyclerView : RecyclerView, newState : Int) { | |||
super.onScrollStateChanged(recyclerView, newState) |
@@ -74,10 +74,13 @@ class LearnWordViewModel : LearnBaseViewModel() { | |||
//数据上传完成监听: true 学习完成的上传 false可能是半途的返回事件,直接退出 | |||
val saveDataLiveData = MutableLiveData<Boolean>() | |||
//是否显示返回弹窗 | |||
private var isShowBackDialog = false | |||
//自动播放模式:是否在自动播放中,默认是 | |||
var isAutoPlaying = true | |||
//当前单词的自动播放次数 | |||
var currentPlayTime = 0 | |||
@@ -87,27 +90,26 @@ class LearnWordViewModel : LearnBaseViewModel() { | |||
*/ | |||
override fun initRunValidTime() { | |||
//自动播放单独定义有效时间规则,播放时时间和总时间一直,停止时播放时,通过触摸判断 | |||
if (learnData.isAutoPlay){ | |||
if (isRunValidTime){ | |||
if (learnData.isAutoPlay) { | |||
if (isRunValidTime) { | |||
validTime.postValue(validTime.value!!.plus(200)) | |||
if (!isAutoPlaying){ //停止播放了 | |||
if (!isAutoPlaying) { //停止播放了 | |||
currentValidSurplusTime -= 200 | |||
isRunValidTime = currentValidSurplusTime > 0 | |||
} | |||
} | |||
}else { | |||
} else { | |||
super.initRunValidTime() | |||
} | |||
} | |||
/** 获取数据 */ | |||
fun loadNext() { | |||
//修改标记 | |||
currentIsHistoricalItemClick = false | |||
//新数据自动播放次数归0 | |||
if (learnData.isAutoPlay){ | |||
if (learnData.isAutoPlay) { | |||
currentPlayTime = 0 | |||
} | |||
@@ -339,9 +341,9 @@ class LearnWordViewModel : LearnBaseViewModel() { | |||
private fun sendEventBus() { | |||
//自动播放不发送信息通知 | |||
if (learnData.isAutoPlay) return | |||
LiveEventBus.get<LearnEventData>(AppConstants.EVENT_LESSON_DATA).post(LearnEventData(learnData.lesson.subjectId, | |||
learnData.lesson.courseId, | |||
AppConstants.DATA_LESSON_LEARN_OVER).apply { | |||
LiveEventBus.get<LearnEventData>(AppConstants.EVENT_LESSON_DATA) | |||
.post(LearnEventData(learnData.lesson.subjectId, learnData.lesson.courseId, | |||
AppConstants.DATA_LESSON_LEARN_OVER).apply { | |||
this.leesonPositionIndex = learnData.lesson.lessonPositionInList | |||
this.newErrorMap = learnData.examErrorMap | |||
}) | |||
@@ -350,7 +352,12 @@ class LearnWordViewModel : LearnBaseViewModel() { | |||
override fun onResume(owner : LifecycleOwner) { | |||
super.onResume(owner) | |||
if (!isAllOver) startTotalCounting() | |||
if (!isAllOver) { | |||
if (!isShowBackDialog || (learnData.isAutoPlay && isAutoPlaying)) { | |||
executeLearnValidTime() | |||
} | |||
startTotalCounting() | |||
} | |||
} | |||
override fun onPause(owner : LifecycleOwner) { |
@@ -57,8 +57,8 @@ class CoursePackMainActivity : BaseActivityVM<ActivityCourseMainBinding, CourseP | |||
//子课程对应的Fragment | |||
private var childFragments = mutableListOf<Fragment>() | |||
//更多按钮的弹窗显示 | |||
private var moreDialog : BottomSheetDialog? = null | |||
// //更多按钮的弹窗显示 | |||
// private var moreDialog : BottomSheetDialog? = null | |||
//自动播放次数的弹窗选择 | |||
private var autoPlaySeletDialog : BottomSheetDialog? = null | |||
@@ -196,8 +196,7 @@ class CoursePackMainActivity : BaseActivityVM<ActivityCourseMainBinding, CourseP | |||
/** 点击显示更多的弹窗 */ | |||
private fun showMoreDialog() { | |||
if (moreDialog == null) { | |||
moreDialog = BottomSheetDialog(this, R.style.dialog_style).apply { | |||
val moreDialog = BottomSheetDialog(this, R.style.dialog_style).apply { | |||
val moreBinding = DataBindingUtil.inflate<DialogBottomCourseMoreBinding>(layoutInflater, | |||
R.layout.dialog_bottom_course_more, null, | |||
false) | |||
@@ -218,9 +217,7 @@ class CoursePackMainActivity : BaseActivityVM<ActivityCourseMainBinding, CourseP | |||
dismiss() | |||
showCourseRelearnDialog() | |||
} | |||
} | |||
} | |||
moreDialog?.show() | |||
}.show() | |||
} | |||
/** 课程重学弹窗提示 */ |
@@ -477,6 +477,8 @@ class CourseLessonFragment : BaseFragmentVM<FragmentCourseLessonBinding, CourseM | |||
} | |||
(requireParentFragment().parentFragment as CourseMainFragment).startExam(examData) | |||
} | |||
//完成,切换到学后总测试fragment | |||
AppConstants.DIALOG_OVER -> (requireParentFragment().parentFragment as CourseMainFragment).changeFragment(2) | |||
} | |||
} | |||
}.show(childFragmentManager, "course_learn_after_test_before") |
@@ -27,9 +27,11 @@ class CourseMainFragment : BaseFragmentVM<FragmentCourseMainBinding, CourseMainF | |||
companion object { | |||
@JvmStatic | |||
fun newInstance(courseIndex : Int) = CourseMainFragment().apply { | |||
arguments = Bundle().apply { | |||
putInt(AppConfig.INTENT_1, courseIndex) | |||
fun newInstance(courseIndex : Int):CourseMainFragment { | |||
return CourseMainFragment().apply { | |||
arguments = Bundle().apply { | |||
putInt(AppConfig.INTENT_1, courseIndex) | |||
} | |||
} | |||
} | |||
} |
@@ -7,6 +7,7 @@ import com.suliang.common.base.viewmodel.BaseViewModel | |||
import com.suliang.common.extension.diskIo2DiskIo | |||
import com.suliang.common.extension.diskIo2Main | |||
import com.suliang.common.util.DateUtil | |||
import com.suliang.common.util.LogUtil | |||
import com.suliang.common.util.file.FileUtil | |||
import com.suliang.common.util.thread.AppExecutors | |||
import com.xkl.cdl.data.AppConstants | |||
@@ -286,10 +287,18 @@ class CourseMainFragmentViewModel(val courseIndex : Int) : BaseViewModel() { | |||
// TODO: 2022/5/6 这里在退出时进行了统计数据缓存保存,在loadMain的时候进行了read缓存 ,后期需要清除 | |||
override fun onDestroy(owner : LifecycleOwner) { | |||
val objectToBytes = FileUtil.objectToBytes(courseDetail) | |||
FileUtil.writeBytesToFile(FileUtil.getSaveDirPath("appcache"), | |||
"${course.subjectId}_${course.coursePackId}_${course.courseId}", objectToBytes) | |||
if (owner is CourseMainFragment) { | |||
LogUtil.e("${this.toString().substringAfterLast(".")} 保存文件 onDestroy") | |||
try { | |||
val objectToBytes = FileUtil.objectToBytes(courseDetail) | |||
FileUtil.writeBytesToFile(FileUtil.getSaveDirPath("appcache"), | |||
"${course.subjectId}_${course.coursePackId}_${course.courseId}", objectToBytes) | |||
} catch (e : Exception) { | |||
e.printStackTrace() | |||
LogUtil.e("${javaClass} 保存文件异常失败") | |||
} | |||
} | |||
super.onDestroy(owner) | |||
} | |||
@@ -14,6 +14,7 @@ import com.xkl.cdl.data.bean.intentdata.ExamData | |||
import com.xkl.cdl.data.manager.CourseManager | |||
import com.xkl.cdl.databinding.FragmentCourseTotalTestBinding | |||
import com.xkl.cdl.module.m_center_learn.CoursePackMainActivity | |||
import java.util.* | |||
/** | |||
* 课程总测试: 学前总,学后总 | |||
@@ -23,9 +24,11 @@ class CourseTotalTestFragment : BaseFragmentVM<FragmentCourseTotalTestBinding, C | |||
companion object { | |||
@JvmStatic | |||
fun newInstance(totalTestType : Int) = CourseTotalTestFragment().apply { | |||
arguments = Bundle().apply { | |||
putInt(AppConfig.INTENT_1, totalTestType) | |||
fun newInstance(totalTestType : Int): CourseTotalTestFragment{ | |||
return CourseTotalTestFragment().apply { | |||
arguments = Bundle().apply { | |||
putInt(AppConfig.INTENT_1, totalTestType) | |||
} | |||
} | |||
} | |||
} | |||
@@ -43,95 +46,94 @@ class CourseTotalTestFragment : BaseFragmentVM<FragmentCourseTotalTestBinding, C | |||
//传递过来的总测类型: 学前,学后 | |||
private var totalTestType = 0 | |||
//测试的数据 | |||
private var testData : List<ExamBean> = emptyList() | |||
override fun initFragment() { | |||
totalTestType = requireArguments().getInt(AppConfig.INTENT_1) | |||
} | |||
override fun loadData() { | |||
vm.loadTest(totalTestType).observe(this) { | |||
testData = it | |||
initView() | |||
when (totalTestType) { | |||
AppConstants.TEST_TYPE_BEFORE_TOTAL -> vm.loadTest(totalTestType).observe(this) { | |||
initTotalBeforeView(it) | |||
} | |||
AppConstants.TEST_TYPE_AFTER_TOTAL -> initTotalAfterView() | |||
} | |||
} | |||
private fun initView() { | |||
binding.tvCountTip.text = CourseManager.expectedTestTime(vm.course.courseType, totalTestType, testData!!) | |||
when (totalTestType) { | |||
AppConstants.TEST_TYPE_BEFORE_TOTAL -> { | |||
// TODO: 2022/4/21 需要把开始学习给取消了 | |||
binding.button1.visibility = View.VISIBLE | |||
//学前总测 | |||
binding.run { | |||
tvTitle.setText(R.string.test_total_before_title) | |||
button1.run { | |||
setText(R.string.start_learn) | |||
click { | |||
continueLearn(it) | |||
/** 学后测试初始 */ | |||
private fun initTotalAfterView() { | |||
binding.run { | |||
ivIcon.setImageResource(if (Random().nextBoolean()) R.mipmap.boy_2 else R.mipmap.girl_2) | |||
tvTitle.setText(R.string.tips_current_course_learn_over) | |||
tvMainTip.visibility = View.VISIBLE | |||
//根据测试成绩处理 | |||
vm.courseDetail.st_before.let { | |||
when (it) { | |||
AppConstants.NOT_DOING -> { //未测 | |||
tvMainTip.setText(R.string.test_total_after_tip_1) | |||
button2.run { | |||
setText(R.string.test_type_after_total) | |||
click { view -> | |||
startTest(view) | |||
} | |||
} | |||
} | |||
//按钮初始 | |||
button2.run { | |||
setText(R.string.start_test) | |||
click { view -> | |||
startTest(view) | |||
else -> { //有成绩,直接完成 | |||
if (it >= AppConstants.TEST_SCORE_LEVEL_2) { | |||
tvMainTip.setHtml("你已完成学后总测试,上次得分: <font color=\'#5082E6\'>$it</font>") | |||
} else { | |||
tvMainTip.setHtml("你已完成学后总测试,上次得分: <font color=\'#F26255\'>$it</font>") | |||
} | |||
} | |||
} | |||
} | |||
AppConstants.TEST_TYPE_AFTER_TOTAL -> { | |||
//学后总测 | |||
binding.run { | |||
ivIcon.setImageResource(if (java.util.Random().nextBoolean()) R.mipmap.boy_2 else R.mipmap.girl_2) | |||
tvTitle.setText(R.string.tips_current_course_learn_over) | |||
tvMainTip.visibility = View.VISIBLE | |||
//根据测试成绩处理 | |||
vm.courseDetail.st_before.let { | |||
when (it) { | |||
AppConstants.NOT_DOING -> { //未测 | |||
tvMainTip.setText(R.string.test_total_after_tip_1) | |||
button2.run { | |||
setText(R.string.test_type_after_total) | |||
click { view -> | |||
startTest(view) | |||
} | |||
} | |||
tvTips.visibility = View.VISIBLE | |||
tvCountTip.visibility = View.GONE | |||
button1.run { | |||
visibility = View.VISIBLE | |||
setText(R.string.test_again) | |||
click { view -> | |||
startTest(view) | |||
} | |||
else -> { //有成绩,直接完成 | |||
if (it >= AppConstants.TEST_SCORE_LEVEL_2) { | |||
tvMainTip.setHtml("你已完成学后总测试,上次得分: <font color=\'#5082E6\'>$it</font>") | |||
}else { | |||
tvMainTip.setHtml("你已完成学后总测试,上次得分: <font color=\'#F26255\'>$it</font>") | |||
} | |||
tvTips.visibility = View.VISIBLE | |||
tvCountTip.visibility = View.GONE | |||
button1.run { | |||
visibility = View.VISIBLE | |||
setText(R.string.test_again) | |||
click { view -> | |||
startTest(view) | |||
} | |||
} | |||
button2.run { | |||
setText(R.string.continue_learn) | |||
click { view -> | |||
continueLearn(view) | |||
} | |||
} | |||
tvClearLearnRecord.visibility = View.VISIBLE | |||
tvClearLearnRecord.click { | |||
(activity as CoursePackMainActivity).showCourseRelearnDialog() | |||
} | |||
} | |||
button2.run { | |||
setText(R.string.continue_learn) | |||
click { view -> | |||
continueLearn(view) | |||
} | |||
} | |||
//清空学习记录 | |||
tvClearLearnRecord.visibility = View.VISIBLE | |||
tvClearLearnRecord.click { | |||
(activity as CoursePackMainActivity).showCourseRelearnDialog() | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
/** 学前测试初始 */ | |||
private fun initTotalBeforeView(testData : List<ExamBean>) { | |||
// TODO: 2022/4/21 需要把开始学习给取消了 | |||
binding.tvCountTip.text = CourseManager.expectedTestTime(vm.course.courseType, totalTestType, testData) | |||
binding.button1.visibility = View.VISIBLE | |||
//学前总测 | |||
binding.run { | |||
tvTitle.setText(R.string.test_total_before_title) | |||
button1.run { | |||
setText(R.string.start_learn) | |||
click { | |||
continueLearn(it) | |||
} | |||
} | |||
//按钮初始 | |||
button2.run { | |||
setText(R.string.start_test) | |||
click { view -> | |||
startTest(view) | |||
} | |||
} | |||
} | |||
} | |||
/**继续学习*/ | |||
private fun continueLearn(view : View) { | |||
(requireParentFragment() as CourseMainFragment).changeFragment(1) | |||
@@ -141,16 +143,18 @@ class CourseTotalTestFragment : BaseFragmentVM<FragmentCourseTotalTestBinding, C | |||
* | |||
*/ | |||
private fun startTest(view : View) { | |||
//生成数据 | |||
val examData = ExamData(vm.course.subjectId, totalTestType, vm.course.courseTitle, vm.course.courseTitle).apply { | |||
coursePackId = vm.course.coursePackId | |||
coursePackType = vm.course.coursePackType | |||
courseId = vm.course.courseId | |||
courseType = vm.course.courseType | |||
this.testData = this@CourseTotalTestFragment.testData | |||
mExamWRMap = if (examType == AppConstants.TEST_TYPE_BEFORE_TOTAL) vm.courseDetail.exam_w_r_list else null | |||
vm.loadTest(totalTestType).observe(this) { | |||
//生成数据 | |||
val examData = ExamData(vm.course.subjectId, totalTestType, vm.course.courseTitle, vm.course.courseTitle).apply { | |||
coursePackId = vm.course.coursePackId | |||
coursePackType = vm.course.coursePackType | |||
courseId = vm.course.courseId | |||
courseType = vm.course.courseType | |||
this.testData = it | |||
mExamWRMap = if (examType == AppConstants.TEST_TYPE_BEFORE_TOTAL) vm.courseDetail.exam_w_r_list else null | |||
} | |||
(parentFragment as CourseMainFragment).startExam(examData) | |||
} | |||
(parentFragment as CourseMainFragment).startExam(examData) | |||
} | |||
} |
@@ -291,10 +291,10 @@ | |||
<!-- app:constraint_referenced_ids="tv_title,inc_statistics_number,tv_learn_over_tip,tv_learn_over_for_after_count_time,tv_left,vSplit"/>--> | |||
<!--课时学后测试结束绑定的布局组 --> | |||
<!-- <androidx.constraintlayout.widget.Group | |||
<!--<androidx.constraintlayout.widget.Group | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
app:constraint_referenced_ids="tv_score,tv_tip,tv_title,inc_statistics_number,tv_top,tv_left,vSplit,tv_top_1" | |||
app:constraint_referenced_ids="tv_score,tv_tip,tv_title,inc_statistics_number,tv_top,tv_left,vSplit" | |||
/>--> | |||
@@ -20,11 +20,13 @@ android { | |||
buildTypes { | |||
release { | |||
buildConfigField("Boolean","LOG_ENABLE","false") | |||
buildConfigField("Boolean","SHOW_LIFECYCLER_LOG","false") | |||
minifyEnabled false | |||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' | |||
} | |||
debug { | |||
buildConfigField("Boolean","LOG_ENABLE","true") | |||
buildConfigField("Boolean","SHOW_LIFECYCLER_LOG","false") | |||
minifyEnabled false | |||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' | |||
} |
@@ -2,6 +2,7 @@ package com.suliang.common.base.activity | |||
import androidx.viewbinding.ViewBinding | |||
import com.suliang.common.extension.initBinding | |||
import com.suliang.common.util.LogUtil | |||
/** |
@@ -2,6 +2,7 @@ package com.suliang.common.base.activity | |||
import android.os.Bundle | |||
import androidx.appcompat.app.AppCompatActivity | |||
import com.suliang.common.BuildConfig | |||
import com.suliang.common.util.LogUtil | |||
/** | |||
@@ -10,48 +11,49 @@ import com.suliang.common.util.LogUtil | |||
* Describe: 打印生命周期的Activity | |||
*/ | |||
open class LifecycleLogActivity : AppCompatActivity() { | |||
// override fun onCreate(savedInstanceState: Bundle?) { | |||
// super.onCreate(savedInstanceState) | |||
// LogUtil.e("onCreate()") | |||
// } | |||
// | |||
// override fun onRestart() { | |||
// super.onRestart() | |||
// LogUtil.e("onRestart()") | |||
// } | |||
// | |||
// override fun onStart() { | |||
// super.onStart() | |||
// LogUtil.e("onStart()") | |||
// } | |||
// | |||
// override fun onResume() { | |||
// super.onResume() | |||
// LogUtil.e("onResume()") | |||
// } | |||
// | |||
// override fun onPause() { | |||
// super.onPause() | |||
// LogUtil.e("onPause()") | |||
// } | |||
// | |||
// override fun onStop() { | |||
// super.onStop() | |||
// LogUtil.e("onStop()") | |||
// } | |||
// | |||
// override fun onDestroy() { | |||
// super.onDestroy() | |||
// LogUtil.e("onDestroy()") | |||
// } | |||
// | |||
// override fun onSaveInstanceState(outState: Bundle) { | |||
// super.onSaveInstanceState(outState) | |||
// LogUtil.e("onSaveInstanceState()") | |||
// } | |||
// | |||
// override fun onRestoreInstanceState(savedInstanceState: Bundle) { | |||
// super.onRestoreInstanceState(savedInstanceState) | |||
// LogUtil.e("onRestoreInstanceState()") | |||
// } | |||
override fun onCreate(savedInstanceState : Bundle?) { | |||
super.onCreate(savedInstanceState) | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e("${this.toString().substringAfterLast(".")} onCreate()") | |||
} | |||
override fun onRestart() { | |||
super.onRestart() | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e("${this.toString().substringAfterLast(".")} onRestart()") | |||
} | |||
override fun onStart() { | |||
super.onStart() | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e("${this.toString().substringAfterLast(".")} onStart()") | |||
} | |||
override fun onResume() { | |||
super.onResume() | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e("${this.toString().substringAfterLast(".")} onResume()") | |||
} | |||
override fun onPause() { | |||
super.onPause() | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e("${this.toString().substringAfterLast(".")} onPause()") | |||
} | |||
override fun onStop() { | |||
super.onStop() | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e("${this.toString().substringAfterLast(".")} onStop()") | |||
} | |||
override fun onDestroy() { | |||
super.onDestroy() | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e("${this.toString().substringAfterLast(".")} onDestroy()") | |||
} | |||
override fun onSaveInstanceState(outState : Bundle) { | |||
super.onSaveInstanceState(outState) | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e("onSaveInstanceState()") | |||
} | |||
override fun onRestoreInstanceState(savedInstanceState : Bundle) { | |||
super.onRestoreInstanceState(savedInstanceState) | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e("onRestoreInstanceState()") | |||
} | |||
} |
@@ -123,7 +123,7 @@ abstract class BaseRVAdapter<T> : | |||
} ?: size | |||
mData.add(startPosition,data) | |||
notifyItemInserted(startPosition) | |||
notifyItemRangeChanged(startPosition,mData.size + 1) | |||
notifyItemRangeChanged(startPosition,mData.size) | |||
} | |||
} | |||
@@ -146,14 +146,15 @@ abstract class BaseRVAdapter<T> : | |||
//通知有新的item插入进来了 | |||
notifyItemInserted(startPosition) | |||
//范围性更新,直接调用onBindViewHolder | |||
notifyItemRangeChanged(startPosition, mData.size + 1 ) | |||
notifyItemRangeChanged(startPosition, mData.size) | |||
} | |||
} | |||
fun removeData(position:Int){ | |||
if(mData.size >= position){ | |||
mData.removeAt(position) | |||
notifyItemRangeChanged(position,mData.size-position) | |||
notifyItemRemoved(position) | |||
notifyItemRangeChanged(0,mData.size) | |||
} | |||
} | |||
@@ -29,7 +29,7 @@ import com.suliang.common.util.LogUtil | |||
* | |||
* @property VB : ViewDataBinding | |||
*/ | |||
abstract class BaseFragment<VB : ViewBinding> : Fragment(),ViewBehavior { | |||
abstract class BaseFragment<VB : ViewBinding> : LifecycleLogFragment(), ViewBehavior { | |||
private var _binding: VB? = null | |||
@@ -2,7 +2,7 @@ package com.suliang.common.base.fragment | |||
import android.content.Context | |||
import android.os.Bundle | |||
import android.util.Log | |||
import com.suliang.common.BuildConfig | |||
import android.view.LayoutInflater | |||
import android.view.View | |||
import android.view.ViewGroup | |||
@@ -14,83 +14,96 @@ import com.suliang.common.util.LogUtil | |||
* create 2022/3/7 14:14 | |||
* Describe: Fragment生命周期日志打印 | |||
*/ | |||
class LifecycleLogFragment : Fragment() { | |||
override fun onAttach(context: Context) { | |||
open class LifecycleLogFragment : Fragment() { | |||
override fun onAttach(context : Context) { | |||
super.onAttach(context) | |||
LogUtil.d("onAttach") | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e( | |||
"${this.toString().substringAfterLast(".").substringBeforeLast(" (")} onAttach()") | |||
} | |||
override fun onCreate(savedInstanceState: Bundle?) { | |||
override fun onCreate(savedInstanceState : Bundle?) { | |||
super.onCreate(savedInstanceState) | |||
LogUtil.d("onCreate") | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e( | |||
"${this.toString().substringAfterLast(".").substringBeforeLast(" (")} onCreate()") | |||
} | |||
override fun onCreateView( | |||
inflater: LayoutInflater, | |||
container: ViewGroup?, | |||
savedInstanceState: Bundle? | |||
): View? { | |||
LogUtil.d("onCreateView") | |||
override fun onCreateView(inflater : LayoutInflater, container : ViewGroup?, savedInstanceState : Bundle?) : View? { | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e( | |||
"${this.toString().substringAfterLast(".").substringBeforeLast(" (")} onCreateView()") | |||
return super.onCreateView(inflater, container, savedInstanceState) | |||
} | |||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | |||
override fun onViewCreated(view : View, savedInstanceState : Bundle?) { | |||
super.onViewCreated(view, savedInstanceState) | |||
LogUtil.d("onViewCreated") | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e( | |||
"${this.toString().substringAfterLast(".").substringBeforeLast(" (")} onCreateView()") | |||
} | |||
// override fun onActivityCreated(savedInstanceState: Bundle?) { | |||
// super.onActivityCreated(savedInstanceState) | |||
// LogUtil.d("onActivityCreated") | |||
// } | |||
override fun onActivityCreated(savedInstanceState : Bundle?) { | |||
super.onActivityCreated(savedInstanceState) | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.d("onActivityCreated") | |||
} | |||
override fun onStart() { | |||
super.onStart() | |||
LogUtil.d("onStart") | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e( | |||
"${this.toString().substringAfterLast(".").substringBeforeLast(" (")} onStart()") | |||
} | |||
override fun onResume() { | |||
super.onResume() | |||
LogUtil.d("onResume") | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e( | |||
"${this.toString().substringAfterLast(".").substringBeforeLast(" (")} onResume()") | |||
} | |||
override fun onStop() { | |||
super.onStop() | |||
LogUtil.d("onStop") | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e( | |||
"${this.toString().substringAfterLast(".").substringBeforeLast(" (")} onStop()") | |||
} | |||
override fun onDestroyView() { | |||
super.onDestroyView() | |||
LogUtil.d("onDestroyView") | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e( | |||
"${this.toString().substringAfterLast(".").substringBeforeLast(" (")} onDestroyView()") | |||
} | |||
override fun onDetach() { | |||
super.onDetach() | |||
LogUtil.d("onDetach") | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e( | |||
"${this.toString().substringAfterLast(".").substringBeforeLast(" (")} onDetach()") | |||
} | |||
override fun onDestroy() { | |||
super.onDestroy() | |||
LogUtil.d("onDestroy") | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e( | |||
"${this.toString().substringAfterLast(".").substringBeforeLast(" (")} onDestroy()") | |||
} | |||
override fun onHiddenChanged(hidden: Boolean) { | |||
override fun onHiddenChanged(hidden : Boolean) { | |||
super.onHiddenChanged(hidden) | |||
LogUtil.d("onHiddenChanged : hidden -> : $hidden" ) | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e( | |||
"${this.toString().substringAfterLast(".").substringBeforeLast(" (")} onHiddenChanged() : hidden -> : $hidden") | |||
} | |||
override fun setUserVisibleHint(isVisibleToUser: Boolean) { | |||
override fun setUserVisibleHint(isVisibleToUser : Boolean) { | |||
super.setUserVisibleHint(isVisibleToUser) | |||
LogUtil.d("setUserVisibleHint: isVisibleToUser -> $isVisibleToUser ") | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e("${ | |||
this.toString() | |||
.substringAfterLast(".") | |||
.substringBeforeLast(" (") | |||
} setUserVisibleHint(): isVisibleToUser -> $isVisibleToUser") | |||
} | |||
override fun onSaveInstanceState(outState: Bundle) { | |||
override fun onSaveInstanceState(outState : Bundle) { | |||
super.onSaveInstanceState(outState) | |||
LogUtil.d(javaClass.simpleName + " onSaveInstanceState()") | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e( | |||
"${this.toString().substringAfterLast(".").substringBeforeLast(" (")} onSaveInstanceState()") | |||
} | |||
override fun onViewStateRestored(savedInstanceState: Bundle?) { | |||
override fun onViewStateRestored(savedInstanceState : Bundle?) { | |||
super.onViewStateRestored(savedInstanceState) | |||
LogUtil.d(javaClass.simpleName + " onViewStateRestored()") | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e( | |||
"${this.toString().substringAfterLast(".").substringBeforeLast(" (")} onViewStateRestored()") | |||
} | |||
} |
@@ -1,9 +1,8 @@ | |||
package com.suliang.common.base.viewmodel | |||
import android.widget.Toast | |||
import androidx.lifecycle.LifecycleOwner | |||
import androidx.lifecycle.MutableLiveData | |||
import androidx.lifecycle.ViewModel | |||
import com.suliang.common.BuildConfig | |||
import com.suliang.common.base.ViewBehavior | |||
import com.suliang.common.base.activity.ToastEvent | |||
import com.suliang.common.util.LogUtil | |||
@@ -14,55 +13,29 @@ import com.suliang.common.util.LogUtil | |||
* Describe: | |||
*/ | |||
open class BaseViewModel : ViewModel(), ViewModelLifecycle, ViewBehavior { | |||
override fun onCreate(owner: LifecycleOwner) { | |||
super.onCreate(owner) | |||
LogUtil.i("${javaClass.name}_${hashCode()} onCreate() ") | |||
} | |||
override fun onStart(owner: LifecycleOwner) { | |||
super.onStart(owner) | |||
LogUtil.i("${javaClass.name}_${hashCode()} onStart() ") | |||
} | |||
override fun onResume(owner: LifecycleOwner) { | |||
super.onResume(owner) | |||
LogUtil.i("${javaClass.name}_${hashCode()} onResume() ") | |||
} | |||
override fun onPause(owner: LifecycleOwner) { | |||
super.onPause(owner) | |||
LogUtil.i("${javaClass.name}_${hashCode()} onPause() ") | |||
} | |||
override fun onStop(owner: LifecycleOwner) { | |||
super.onStop(owner) | |||
LogUtil.i("${javaClass.name}_${hashCode()} onStop() ") | |||
} | |||
override fun onDestroy(owner: LifecycleOwner) { | |||
super.onDestroy(owner) | |||
LogUtil.i("${javaClass.name}_${hashCode()} onDestroy() ") | |||
} | |||
override fun onCleared() { | |||
super.onCleared() | |||
LogUtil.i("${javaClass.name}_${hashCode()} onCleared() ") | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e("${this.toString().substringAfterLast(".")} onCleared() ") | |||
} | |||
val loadingEvent = MutableLiveData<Boolean>() | |||
val toastEvent = MutableLiveData<ToastEvent>() | |||
val pageEvent = MutableLiveData<Class<*>>() | |||
override fun showHideLoading(isShow: Boolean) { | |||
override fun showHideLoading(isShow : Boolean) { | |||
loadingEvent.postValue(isShow) | |||
} | |||
override fun showToast(msg: ToastEvent) { | |||
override fun showToast(msg : ToastEvent) { | |||
toastEvent.postValue(msg) | |||
} | |||
override fun startActivity(clazz: Class<*>) { | |||
override fun startActivity(clazz : Class<*>) { | |||
pageEvent.postValue(clazz) | |||
} | |||
} | |||
@@ -1,12 +1,38 @@ | |||
package com.suliang.common.base.viewmodel | |||
import androidx.lifecycle.DefaultLifecycleObserver | |||
import androidx.lifecycle.LifecycleOwner | |||
import com.suliang.common.BuildConfig | |||
import com.suliang.common.util.LogUtil | |||
/** | |||
* author suliang | |||
* create 2022/3/17 11:22 | |||
* Describe: ViewModel生命周期 与 Activity/Fragment同步 | |||
*/ | |||
* author suliang | |||
* create 2022/3/17 11:22 | |||
* Describe: ViewModel生命周期 与 Activity/Fragment同步 | |||
* // DefaultLifecycleObserver | |||
*/ | |||
interface ViewModelLifecycle : DefaultLifecycleObserver { | |||
override fun onCreate(owner : LifecycleOwner) { | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e("${this.toString().substringAfterLast(".")} onCreate() ") | |||
} | |||
override fun onStart(owner : LifecycleOwner) { | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.i("${this.toString().substringAfterLast(".")} onStart() ") | |||
} | |||
override fun onResume(owner : LifecycleOwner) { | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.i("${this.toString().substringAfterLast(".")} onResume() ") | |||
} | |||
override fun onPause(owner : LifecycleOwner) { | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.i("${this.toString().substringAfterLast(".")} onPause() ") | |||
} | |||
override fun onStop(owner : LifecycleOwner) { | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.i("${this.toString().substringAfterLast(".")} onStop() ") | |||
} | |||
override fun onDestroy(owner : LifecycleOwner) { | |||
if (BuildConfig.SHOW_LIFECYCLER_LOG) LogUtil.e("${this.toString().substringAfterLast(".")} onDestroy() ") | |||
} | |||
} |
@@ -38,13 +38,14 @@ object LogUtil { | |||
private fun log(logType: String, message: String) { | |||
if (!LogEnable) return | |||
val stackTraceElement = Thread.currentThread().stackTrace[5] | |||
val out = "==${stackTraceElement.methodName} : ${stackTraceElement.lineNumber} --- $message ===== " | |||
val className = stackTraceElement.className.substringAfterLast(".") | |||
val out = "==> \n${className}_${stackTraceElement.methodName.substringAfterLast(".")}_${stackTraceElement.lineNumber} \n$message" | |||
when(logType){ | |||
"v" -> Log.v(stackTraceElement.className,out) | |||
"d" -> Log.d(stackTraceElement.className,out) | |||
"e" -> Log.e(stackTraceElement.className,out) | |||
"i" -> Log.i(stackTraceElement.className,out) | |||
"w" -> Log.w(stackTraceElement.className,out) | |||
"v" -> Log.v(className,out) | |||
"d" -> Log.d(className,out) | |||
"e" -> Log.e(className,out) | |||
"i" -> Log.i(className,out) | |||
"w" -> Log.w(className,out) | |||
} | |||
} | |||
@@ -148,7 +148,7 @@ internal class MPUtil : IMP,MediaPlayer.OnPreparedListener,MediaPlayer.OnErrorLi | |||
/** 异步准备完毕 ,开始播放*/ | |||
private fun handlePrepared() { | |||
if (currentState == EMediaState.PREPARED) { //修改为播放状态,调用播放 | |||
LogUtil.i("准备完成,开始播放") | |||
// LogUtil.i("准备完成,开始播放") | |||
mediaPlayer?.start() | |||
currentState = EMediaState.RUNNING | |||
handleListener() | |||
@@ -306,7 +306,7 @@ internal class MPUtil : IMP,MediaPlayer.OnPreparedListener,MediaPlayer.OnErrorLi | |||
} | |||
override fun onPrepared(mp: MediaPlayer?) { | |||
LogUtil.i("mOnPreparedLister 回调") | |||
// LogUtil.i("mOnPreparedLister 回调") | |||
if (currentState == EMediaState.INITIALIZED || currentState == EMediaState.PREPARING) { | |||
currentState = EMediaState.PREPARED | |||
handlePrepared() |
@@ -54,7 +54,7 @@ object ScreenUtil { | |||
//根据资源Id获取相应的尺寸 | |||
statusBarHeight = resources.getDimensionPixelSize(resourceId) | |||
} | |||
LogUtil.d(" 状态栏高度 navigationBarHeight = $statusBarHeight") | |||
// LogUtil.d(" 状态栏高度 navigationBarHeight = $statusBarHeight") | |||
return statusBarHeight | |||
} | |||