pref: 优化消息列表代码

This commit is contained in:
HuanCheng65 2021-12-05 15:55:13 +08:00
parent 55ebc34007
commit deabc0600a
4 changed files with 139 additions and 85 deletions

View File

@ -333,6 +333,17 @@ interface ITiebaApi {
page: Int = 1 page: Int = 1
): Call<MessageListBean> ): Call<MessageListBean>
/**
* 回复我的消息列表异步
*
* **需登录**
*
* @param page 分页页码 1 开始
*/
fun replyMeAsync(
page: Int = 1
): Deferred<ApiResult<MessageListBean>>
/** /**
* 提到我的消息列表 * 提到我的消息列表
* *
@ -344,6 +355,17 @@ interface ITiebaApi {
page: Int = 1 page: Int = 1
): Call<MessageListBean> ): Call<MessageListBean>
/**
* 提到我的消息列表异步
*
* **需登录**
*
* @param page 分页页码 1 开始
*/
fun atMeAsync(
page: Int = 1
): Deferred<ApiResult<MessageListBean>>
/** /**
* 赞我的消息列表 * 赞我的消息列表
* *

View File

@ -190,8 +190,14 @@ object MixedTiebaApiImpl : ITiebaApi {
override fun replyMe(page: Int): Call<MessageListBean> = override fun replyMe(page: Int): Call<MessageListBean> =
RetrofitTiebaApi.NEW_TIEBA_API.replyMe(page) RetrofitTiebaApi.NEW_TIEBA_API.replyMe(page)
override fun replyMeAsync(page: Int): Deferred<ApiResult<MessageListBean>> =
RetrofitTiebaApi.NEW_TIEBA_API.replyMeAsync(page)
override fun atMe(page: Int): Call<MessageListBean> = RetrofitTiebaApi.NEW_TIEBA_API.atMe(page) override fun atMe(page: Int): Call<MessageListBean> = RetrofitTiebaApi.NEW_TIEBA_API.atMe(page)
override fun atMeAsync(page: Int): Deferred<ApiResult<MessageListBean>> =
RetrofitTiebaApi.NEW_TIEBA_API.atMeAsync(page)
override fun agreeMe(page: Int): Call<MessageListBean> = override fun agreeMe(page: Int): Call<MessageListBean> =
RetrofitTiebaApi.NEW_TIEBA_API.agreeMe(page) RetrofitTiebaApi.NEW_TIEBA_API.agreeMe(page)

View File

@ -5,6 +5,8 @@ import com.huanchengfly.tieba.post.api.models.CommonResponse
import com.huanchengfly.tieba.post.api.models.MessageListBean import com.huanchengfly.tieba.post.api.models.MessageListBean
import com.huanchengfly.tieba.post.api.models.MsgBean import com.huanchengfly.tieba.post.api.models.MsgBean
import com.huanchengfly.tieba.post.api.models.ThreadStoreBean import com.huanchengfly.tieba.post.api.models.ThreadStoreBean
import com.huanchengfly.tieba.post.api.retrofit.ApiResult
import kotlinx.coroutines.Deferred
import retrofit2.Call import retrofit2.Call
import retrofit2.http.Field import retrofit2.http.Field
import retrofit2.http.FormUrlEncoded import retrofit2.http.FormUrlEncoded
@ -52,6 +54,13 @@ interface NewTiebaApi {
@Field("pn") page: Int = 0 @Field("pn") page: Int = 0
): Call<MessageListBean> ): Call<MessageListBean>
@Headers("${Header.FORCE_LOGIN}: ${Header.FORCE_LOGIN_TRUE}")
@POST("/c/u/feed/replyme")
@FormUrlEncoded
fun replyMeAsync(
@Field("pn") page: Int = 0
): Deferred<ApiResult<MessageListBean>>
@Headers("${Header.FORCE_LOGIN}: ${Header.FORCE_LOGIN_TRUE}") @Headers("${Header.FORCE_LOGIN}: ${Header.FORCE_LOGIN_TRUE}")
@POST("/c/u/feed/atme") @POST("/c/u/feed/atme")
@FormUrlEncoded @FormUrlEncoded
@ -59,6 +68,13 @@ interface NewTiebaApi {
@Field("pn") page: Int = 0 @Field("pn") page: Int = 0
): Call<MessageListBean> ): Call<MessageListBean>
@Headers("${Header.FORCE_LOGIN}: ${Header.FORCE_LOGIN_TRUE}")
@POST("/c/u/feed/atme")
@FormUrlEncoded
fun atMeAsync(
@Field("pn") page: Int = 0
): Deferred<ApiResult<MessageListBean>>
@Headers("${Header.FORCE_LOGIN}: ${Header.FORCE_LOGIN_TRUE}") @Headers("${Header.FORCE_LOGIN}: ${Header.FORCE_LOGIN_TRUE}")
@POST("/c/u/feed/agreeme") @POST("/c/u/feed/agreeme")
@FormUrlEncoded @FormUrlEncoded

View File

@ -1,6 +1,5 @@
package com.huanchengfly.tieba.post.fragments package com.huanchengfly.tieba.post.fragments
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
@ -19,8 +18,10 @@ import com.huanchengfly.tieba.post.activities.NewSearchActivity
import com.huanchengfly.tieba.post.activities.ThreadActivity import com.huanchengfly.tieba.post.activities.ThreadActivity
import com.huanchengfly.tieba.post.adapters.MessageListAdapter import com.huanchengfly.tieba.post.adapters.MessageListAdapter
import com.huanchengfly.tieba.post.adapters.TabViewPagerAdapter import com.huanchengfly.tieba.post.adapters.TabViewPagerAdapter
import com.huanchengfly.tieba.post.api.TiebaApi.getInstance import com.huanchengfly.tieba.post.api.TiebaApi
import com.huanchengfly.tieba.post.api.models.MessageListBean import com.huanchengfly.tieba.post.api.models.MessageListBean
import com.huanchengfly.tieba.post.api.retrofit.doIfFailure
import com.huanchengfly.tieba.post.api.retrofit.doIfSuccess
import com.huanchengfly.tieba.post.api.retrofit.exception.TiebaException import com.huanchengfly.tieba.post.api.retrofit.exception.TiebaException
import com.huanchengfly.tieba.post.components.MyLinearLayoutManager import com.huanchengfly.tieba.post.components.MyLinearLayoutManager
import com.huanchengfly.tieba.post.goToActivity import com.huanchengfly.tieba.post.goToActivity
@ -29,28 +30,26 @@ import com.huanchengfly.tieba.post.utils.ThemeUtil
import com.huanchengfly.tieba.post.utils.Util import com.huanchengfly.tieba.post.utils.Util
import com.scwang.smart.refresh.header.MaterialHeader import com.scwang.smart.refresh.header.MaterialHeader
import com.scwang.smart.refresh.layout.SmartRefreshLayout import com.scwang.smart.refresh.layout.SmartRefreshLayout
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class MessageFragment : BaseFragment(), Refreshable, OnTabSelectedListener, Toolbar.OnMenuItemClickListener { class MessageFragment : BaseFragment(), Refreshable, OnTabSelectedListener,
@JvmField Toolbar.OnMenuItemClickListener {
@BindView(R.id.fragment_message_tab) @BindView(R.id.fragment_message_tab)
var tabLayout: TabLayout? = null lateinit var tabLayout: TabLayout
@JvmField
@BindView(R.id.toolbar) @BindView(R.id.toolbar)
var mToolbar: Toolbar? = null lateinit var toolbar: Toolbar
@JvmField
@BindView(R.id.appbar) @BindView(R.id.appbar)
var mAppBarLayout: AppBarLayout? = null lateinit var mAppBarLayout: AppBarLayout
@BindView(R.id.fragment_message_vp)
lateinit var viewPager: ViewPager
@JvmField
@BindView(R.id.title) @BindView(R.id.title)
var mTitleTextView: TextView? = null lateinit var mTitleTextView: TextView
private var replyMe: MessageListHelper? = null
private var atMe: MessageListHelper? = null private val replyMe: MessageListHelper by lazy { MessageListHelper(TYPE_REPLY_ME) }
private val atMe: MessageListHelper by lazy { MessageListHelper(TYPE_AT_ME) }
var type = 0 var type = 0
private set private set
private var isFromMain = false private var isFromMain = false
@ -73,26 +72,30 @@ class MessageFragment : BaseFragment(), Refreshable, OnTabSelectedListener, Tool
} }
} }
public override fun getLayoutId(): Int { override fun getLayoutId(): Int {
return R.layout.fragment_message return R.layout.fragment_message
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
if (!isFromMain) { if (!isFromMain) {
mToolbar?.visibility = View.GONE toolbar.visibility = View.GONE
(mToolbar?.layoutParams as AppBarLayout.LayoutParams?)?.scrollFlags = SCROLL_FLAG_NO_SCROLL (toolbar.layoutParams as AppBarLayout.LayoutParams?)?.scrollFlags =
SCROLL_FLAG_NO_SCROLL
} }
mToolbar?.setOnMenuItemClickListener(this) toolbar.setOnMenuItemClickListener(this)
val viewPager: ViewPager = view.findViewById(R.id.fragment_message_vp) viewPager.adapter = TabViewPagerAdapter().apply {
val viewPagerAdapter = TabViewPagerAdapter() addView(
replyMe = MessageListHelper(attachContext, TYPE_REPLY_ME) replyMe.requireContentView(),
atMe = MessageListHelper(attachContext, TYPE_AT_ME) attachContext.getString(R.string.title_reply_me)
viewPagerAdapter.addView(replyMe!!.contentView, attachContext.getString(R.string.title_reply_me)) )
viewPagerAdapter.addView(atMe!!.contentView, attachContext.getString(R.string.title_at_me)) addView(
viewPager.adapter = viewPagerAdapter atMe.requireContentView(),
tabLayout!!.setupWithViewPager(viewPager) attachContext.getString(R.string.title_at_me)
tabLayout!!.addOnTabSelectedListener(this) )
}
tabLayout.setupWithViewPager(viewPager)
tabLayout.addOnTabSelectedListener(this)
viewPager.setCurrentItem(type, false) viewPager.setCurrentItem(type, false)
if (!isFromMain) { if (!isFromMain) {
refreshIfNeed() refreshIfNeed()
@ -111,27 +114,27 @@ class MessageFragment : BaseFragment(), Refreshable, OnTabSelectedListener, Tool
} }
override fun onRefresh() { override fun onRefresh() {
when (tabLayout!!.selectedTabPosition) { when (tabLayout.selectedTabPosition) {
0 -> if (isFragmentVisible) { 0 -> replyMe
replyMe!!.refresh(true) 1 -> atMe
else -> null
}?.apply {
if (isFragmentVisible) {
refresh(true)
} else { } else {
replyMe!!.dataBean = null dataBean = null
}
1 -> if (isFragmentVisible) {
atMe!!.refresh(true)
} else {
atMe!!.dataBean = null
} }
} }
} }
private fun refreshIfNeed() { private fun refreshIfNeed() {
when (tabLayout!!.selectedTabPosition) { when (tabLayout.selectedTabPosition) {
0 -> if (replyMe!!.needLoad()) { 0 -> replyMe
replyMe!!.refresh(true) 1 -> atMe
} else -> null
1 -> if (atMe!!.needLoad()) { }?.apply {
atMe!!.refresh(true) if (needLoad()) {
refresh(true)
} }
} }
} }
@ -141,16 +144,17 @@ class MessageFragment : BaseFragment(), Refreshable, OnTabSelectedListener, Tool
} }
override fun onTabUnselected(tab: TabLayout.Tab) {} override fun onTabUnselected(tab: TabLayout.Tab) {}
override fun onTabReselected(tab: TabLayout.Tab) { override fun onTabReselected(tab: TabLayout.Tab) {
refreshIfNeed() refreshIfNeed()
} }
internal inner class MessageListHelper(context: Context?, val type: Int) { internal inner class MessageListHelper(val type: Int) {
val contentView: View? var contentView: View? = null
private val mSmartRefreshLayout: SmartRefreshLayout private lateinit var smartRefreshLayout: SmartRefreshLayout
private val materialHeader: MaterialHeader private lateinit var materialHeader: MaterialHeader
private val recyclerView: RecyclerView private lateinit var recyclerView: RecyclerView
private val adapter: MessageListAdapter private lateinit var adapter: MessageListAdapter
private var page = 0 private var page = 0
var dataBean: MessageListBean? = null var dataBean: MessageListBean? = null
@ -160,7 +164,7 @@ class MessageFragment : BaseFragment(), Refreshable, OnTabSelectedListener, Tool
@JvmOverloads @JvmOverloads
fun refresh(autoRefresh: Boolean = true) { fun refresh(autoRefresh: Boolean = true) {
if (autoRefresh) mSmartRefreshLayout.autoRefresh() if (autoRefresh) smartRefreshLayout.autoRefresh()
load(true) load(true)
} }
@ -169,43 +173,36 @@ class MessageFragment : BaseFragment(), Refreshable, OnTabSelectedListener, Tool
recyclerView.scrollToPosition(0) recyclerView.scrollToPosition(0)
page = 1 page = 1
} }
val messageListBeanCallback: Callback<MessageListBean> = object : Callback<MessageListBean> { launchIO {
override fun onResponse(call: Call<MessageListBean?>, response: Response<MessageListBean?>) { when (type) {
dataBean = response.body() TYPE_AT_ME -> TiebaApi.getInstance().atMeAsync(page)
if (dataBean == null) { else -> TiebaApi.getInstance().replyMeAsync(page)
return }.doIfSuccess {
} dataBean = it
if (reload) { if (reload) {
adapter.reset() adapter.reset()
dataBean?.let { adapter.setData(it) } adapter.setData(it)
recyclerView.scrollToPosition(0) recyclerView.scrollToPosition(0)
} else { } else {
dataBean?.let { adapter.addData(it) } adapter.addData(it)
} }
mSmartRefreshLayout.finishRefresh(true) smartRefreshLayout.finishRefresh(true)
if (dataBean?.page?.hasMore != "1") { if (it.page?.hasMore != "1") {
mSmartRefreshLayout.finishRefreshWithNoMoreData() smartRefreshLayout.finishRefreshWithNoMoreData()
} }
} }.doIfFailure {
override fun onFailure(call: Call<MessageListBean?>, t: Throwable) {
if (reload) { if (reload) {
if (t !is TiebaException) { if (it !is TiebaException) {
Util.showNetworkErrorSnackbar(recyclerView) { refresh() } Util.showNetworkErrorSnackbar(recyclerView) { refresh() }
return
} }
} }
if (reload) { if (reload) {
mSmartRefreshLayout.finishRefresh(false) smartRefreshLayout.finishRefresh(false)
} else { } else {
mSmartRefreshLayout.finishLoadMore(false) smartRefreshLayout.finishLoadMore(false)
} }
} }
} }
when (type) {
TYPE_REPLY_ME -> getInstance().replyMe(page).enqueue(messageListBeanCallback)
TYPE_AT_ME -> getInstance().atMe(page).enqueue(messageListBeanCallback)
}
} }
private fun loadMore() { private fun loadMore() {
@ -213,31 +210,39 @@ class MessageFragment : BaseFragment(), Refreshable, OnTabSelectedListener, Tool
page += 1 page += 1
load(false) load(false)
} else { } else {
mSmartRefreshLayout.finishLoadMoreWithNoMoreData() smartRefreshLayout.finishLoadMoreWithNoMoreData()
} }
} }
init { fun requireContentView(): View {
require(!(this.type != TYPE_REPLY_ME && this.type != TYPE_AT_ME)) { "参数不正确" }
contentView = Util.inflate(context, R.layout.fragment_message_list)
if (contentView == null) { if (contentView == null) {
throw NullPointerException("引入的布局为空") initView()
}
return contentView!!
}
fun initView() {
contentView = Util.inflate(attachContext, R.layout.fragment_message_list)!!.also {
recyclerView = it.findViewById(R.id.fragment_message_recycler_view)
smartRefreshLayout = it.findViewById(R.id.fragment_message_refresh_layout)
materialHeader = it.findViewById(R.id.refresh_header)
} }
recyclerView = contentView.findViewById(R.id.fragment_message_recycler_view)
mSmartRefreshLayout = contentView.findViewById(R.id.fragment_message_refresh_layout)
materialHeader = contentView.findViewById(R.id.refresh_header)
ThemeUtil.setThemeForMaterialHeader(materialHeader) ThemeUtil.setThemeForMaterialHeader(materialHeader)
mSmartRefreshLayout.setOnRefreshListener { smartRefreshLayout.setOnRefreshListener {
refresh(false) refresh(false)
} }
mSmartRefreshLayout.setOnLoadMoreListener { smartRefreshLayout.setOnLoadMoreListener {
loadMore() loadMore()
} }
recyclerView.layoutManager = MyLinearLayoutManager(context) recyclerView.layoutManager = MyLinearLayoutManager(context)
adapter = MessageListAdapter(context!!, type).apply { adapter = MessageListAdapter(context!!, type).apply {
setOnItemClickListener { _, item, _ -> setOnItemClickListener { _, item, _ ->
if (item.isFloor == "1") { if (item.isFloor == "1") {
FloorActivity.launch(attachContext, item.threadId!!, subPostId = item.postId) FloorActivity.launch(
attachContext,
item.threadId!!,
subPostId = item.postId
)
} else { } else {
ThreadActivity.launch(context, item.threadId!!, item.postId) ThreadActivity.launch(context, item.threadId!!, item.postId)
} }
@ -245,12 +250,17 @@ class MessageFragment : BaseFragment(), Refreshable, OnTabSelectedListener, Tool
} }
recyclerView.adapter = adapter recyclerView.adapter = adapter
} }
init {
require(!(this.type != TYPE_REPLY_ME && this.type != TYPE_AT_ME)) { "参数不正确" }
initView()
}
} }
companion object { companion object {
const val TYPE_REPLY_ME = 0 const val TYPE_REPLY_ME = 0
const val TYPE_AT_ME = 1 const val TYPE_AT_ME = 1
val TAG = MessageFragment::class.java.simpleName val TAG: String = MessageFragment::class.java.simpleName
private const val PARAM_TYPE = "type" private const val PARAM_TYPE = "type"
const val PARAM_FROM_MAIN = "from_main" const val PARAM_FROM_MAIN = "from_main"