From 3ec9e823eebafc76ea596fe7efdfa2e3792d27a7 Mon Sep 17 00:00:00 2001 From: HuanCheng65 <22636177+HuanCheng65@users.noreply.github.com> Date: Thu, 16 Jun 2022 09:24:43 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E7=A9=BA=E6=8C=87=E9=92=88=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapters/PersonalizedFeedAdapter.java | 42 ++--- .../post/adapters/ThreadMainPostAdapter.kt | 4 +- .../tieba/post/api/interfaces/ITiebaApi.kt | 11 ++ .../api/interfaces/impls/MixedTiebaApiImpl.kt | 6 + .../api/retrofit/interfaces/MiniTiebaApi.kt | 27 +++ .../fragments/PersonalizedFeedFragment.kt | 177 ++++++++++-------- 6 files changed, 171 insertions(+), 96 deletions(-) diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/PersonalizedFeedAdapter.java b/app/src/main/java/com/huanchengfly/tieba/post/adapters/PersonalizedFeedAdapter.java index deacfc2d..8fcf463b 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/adapters/PersonalizedFeedAdapter.java +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/PersonalizedFeedAdapter.java @@ -15,8 +15,10 @@ import com.bumptech.glide.Glide; import com.huanchengfly.tieba.post.BaseApplication; import com.huanchengfly.tieba.post.ExtensionsKt; import com.huanchengfly.tieba.post.R; +import com.huanchengfly.tieba.post.adapters.base.BaseMultiTypeAdapter; import com.huanchengfly.tieba.post.api.models.ForumPageBean; import com.huanchengfly.tieba.post.api.models.PersonalizedBean; +import com.huanchengfly.tieba.post.components.MyViewHolder; import com.huanchengfly.tieba.post.components.dialogs.DislikeDialog; import com.huanchengfly.tieba.post.models.PhotoViewBean; import com.huanchengfly.tieba.post.utils.DateTimeUtils; @@ -27,27 +29,25 @@ import com.huanchengfly.tieba.post.utils.SharedPreferencesUtil; import com.huanchengfly.tieba.post.utils.Util; import com.huanchengfly.tieba.post.widgets.MarkedImageView; import com.huanchengfly.tieba.post.widgets.VideoPlayerStandard; -import com.othershe.baseadapter.ViewHolder; -import com.othershe.baseadapter.base.MultiBaseAdapter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -public class PersonalizedFeedAdapter extends MultiBaseAdapter { +public class PersonalizedFeedAdapter extends BaseMultiTypeAdapter { public static final int TYPE_THREAD_COMMON = 11; public static final int TYPE_THREAD_SINGLE_PIC = 12; public static final int TYPE_THREAD_MULTI_PIC = 13; public static final int TYPE_THREAD_VIDEO = 14; - private NavigationHelper navigationHelper; + private final NavigationHelper navigationHelper; private int refreshPosition; private OnRefreshListener onRefreshListener; public PersonalizedFeedAdapter(Context context) { - super(context, null, false); + super(context); refreshPosition = -1; navigationHelper = NavigationHelper.newInstance(context); } @@ -70,9 +70,9 @@ public class PersonalizedFeedAdapter extends MultiBaseAdapter { if (position <= refreshPosition && refreshPosition > -1) { refreshPosition -= 1; @@ -208,19 +208,19 @@ public class PersonalizedFeedAdapter extends MultiBaseAdapter NavigationHelper.toUserSpaceWithAnim(mContext, authorBean.getId(), authorBean.getPortrait(), v)); + viewHolder.setOnClickListener(R.id.forum_item_user_avatar, v -> NavigationHelper.toUserSpaceWithAnim(getContext(), authorBean.getId(), authorBean.getPortrait(), v)); viewHolder.setText(R.id.forum_item_user_name, authorBean.getNameShow()); ImageUtil.load(viewHolder.getView(R.id.forum_item_user_avatar), ImageUtil.LOAD_TYPE_AVATAR, authorBean.getPortrait()); } TextView timeTextView = viewHolder.getView(R.id.forum_item_user_time); String relativeTime = - DateTimeUtils.getRelativeTimeString(mContext, threadBean.getLastTimeInt()); + DateTimeUtils.getRelativeTimeString(getContext(), threadBean.getLastTimeInt()); if (!TextUtils.isEmpty(threadBean.getForumName())) { timeTextView.setText( - mContext.getString( + getContext().getString( R.string.template_two_string, relativeTime, - mContext.getString(R.string.text_forum_name, threadBean.getForumName()) + getContext().getString(R.string.text_forum_name, threadBean.getForumName()) ) ); } else { @@ -228,7 +228,7 @@ public class PersonalizedFeedAdapter extends MultiBaseAdapter= 2) { @@ -264,7 +264,7 @@ public class PersonalizedFeedAdapter extends MultiBaseAdapter= 3) { @@ -273,7 +273,7 @@ public class PersonalizedFeedAdapter extends MultiBaseAdapter 3) { diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/ThreadMainPostAdapter.kt b/app/src/main/java/com/huanchengfly/tieba/post/adapters/ThreadMainPostAdapter.kt index 4c0c1243..62b5a523 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/adapters/ThreadMainPostAdapter.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/ThreadMainPostAdapter.kt @@ -186,12 +186,12 @@ class ThreadMainPostAdapter( } val forumNameView = forumView.findViewById(R.id.forum_bar_name) val forumAvatarView: ImageView = forumView.findViewById(R.id.forum_bar_avatar) - if (!showForum || !context.appPreferences.showShortcutInThread || "0" == forumInfoBean.isExists || forumInfoBean.name!!.isEmpty()) { + if (!showForum || !context.appPreferences.showShortcutInThread || "0" == forumInfoBean.isExists || forumInfoBean.name?.isEmpty() == true) { forumView.visibility = View.GONE return } forumView.visibility = View.VISIBLE - forumView.setOnClickListener(View.OnClickListener { launch(context, forumInfoBean.name) }) + forumView.setOnClickListener(View.OnClickListener { launch(context, forumInfoBean.name!!) }) forumNameView.text = forumInfoBean.name ImageUtil.load(forumAvatarView, ImageUtil.LOAD_TYPE_AVATAR, forumInfoBean.avatar) } diff --git a/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/ITiebaApi.kt b/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/ITiebaApi.kt index b9d20fb5..59415491 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/ITiebaApi.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/ITiebaApi.kt @@ -27,6 +27,17 @@ interface ITiebaApi { page: Int = 1 ): Call + /** + * 个性推荐(每页 15 贴) + * + * @param loadType 加载类型(1 - 下拉刷新 2 - 加载更多) + * @param page 分页页码 + */ + fun personalizedAsync( + loadType: Int, + page: Int = 1 + ): Deferred> + /** * 给贴子/回复点赞 * diff --git a/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/impls/MixedTiebaApiImpl.kt b/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/impls/MixedTiebaApiImpl.kt index ece69c57..4ce07a72 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/impls/MixedTiebaApiImpl.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/impls/MixedTiebaApiImpl.kt @@ -30,6 +30,12 @@ object MixedTiebaApiImpl : ITiebaApi { override fun personalized(loadType: Int, page: Int): Call = RetrofitTiebaApi.MINI_TIEBA_API.personalized(loadType, page) + override fun personalizedAsync( + loadType: Int, + page: Int + ): Deferred> = + RetrofitTiebaApi.MINI_TIEBA_API.personalizedAsync(loadType, page) + override fun myProfileAsync(): Deferred> = RetrofitTiebaApi.WEB_TIEBA_API.myProfileAsync("json", "", "") diff --git a/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interfaces/MiniTiebaApi.kt b/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interfaces/MiniTiebaApi.kt index 1d2851b3..9ea25e63 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interfaces/MiniTiebaApi.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interfaces/MiniTiebaApi.kt @@ -42,6 +42,33 @@ interface MiniTiebaApi { @Field("scr_w") scr_w: String = getScreenWidth().toString() ): Call + @POST("/c/f/excellent/personalized") + @FormUrlEncoded + fun personalizedAsync( + @Field("load_type") load_type: Int, + @Field("pn") page: Int = 1, + @retrofit2.http.Header("client_user_token") client_user_token: String? = AccountUtil.getUid( + BaseApplication.instance + ), + @Field("_client_version") client_version: String = "8.0.8.0", + @retrofit2.http.Header(Header.USER_AGENT) user_agent: String = "bdtb for Android $client_version", + @Field("cuid_gid") cuid_gid: String = "", + @Field("need_tags") need_tags: Int = 0, + @Field("page_thread_count") page_thread_count: Int = 15, + @Field("pre_ad_thread_count") pre_ad_thread_count: Int = 0, + @Field("sug_count") sug_count: Int = 0, + @Field("tag_code") tag_code: Int = 0, + @Field("q_type") q_type: Int = 1, + @Field("need_forumlist") need_forumlist: Int = 0, + @Field("new_net_type") new_net_type: Int = 1, + @Field("new_install") new_install: Int = 0, + @Field("request_time") request_time: Long = System.currentTimeMillis(), + @Field("invoke_source") invoke_source: String = "", + @Field("scr_dip") scr_dip: String = ScreenInfo.DENSITY.toString(), + @Field("scr_h") scr_h: String = getScreenHeight().toString(), + @Field("scr_w") scr_w: String = getScreenWidth().toString() + ): Deferred> + @Headers("${Header.FORCE_LOGIN}: ${Header.FORCE_LOGIN_TRUE}") @POST("/c/c/agree/opAgree") @FormUrlEncoded diff --git a/app/src/main/java/com/huanchengfly/tieba/post/fragments/PersonalizedFeedFragment.kt b/app/src/main/java/com/huanchengfly/tieba/post/fragments/PersonalizedFeedFragment.kt index cef696d0..e6d9bcd7 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/fragments/PersonalizedFeedFragment.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/fragments/PersonalizedFeedFragment.kt @@ -1,11 +1,10 @@ package com.huanchengfly.tieba.post.fragments -import android.animation.Animator -import android.animation.AnimatorListenerAdapter import android.content.res.Configuration import android.os.Bundle import android.view.MenuItem import android.view.View +import android.view.animation.AccelerateDecelerateInterpolator import android.widget.TextView import android.widget.Toast import androidx.appcompat.widget.Toolbar @@ -21,6 +20,8 @@ import com.huanchengfly.tieba.post.activities.NewSearchActivity import com.huanchengfly.tieba.post.adapters.PersonalizedFeedAdapter import com.huanchengfly.tieba.post.api.TiebaApi import com.huanchengfly.tieba.post.api.models.PersonalizedBean +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.components.MyLinearLayoutManager import com.huanchengfly.tieba.post.components.dividers.FeedDivider @@ -29,7 +30,11 @@ import com.huanchengfly.tieba.post.goToActivity import com.huanchengfly.tieba.post.interfaces.Refreshable import com.huanchengfly.tieba.post.isLandscape import com.huanchengfly.tieba.post.isPortrait -import com.huanchengfly.tieba.post.utils.* +import com.huanchengfly.tieba.post.utils.BlockUtil +import com.huanchengfly.tieba.post.utils.ThemeUtil +import com.huanchengfly.tieba.post.utils.TiebaUtil +import com.huanchengfly.tieba.post.utils.Util +import com.huanchengfly.tieba.post.utils.anim.animSet import com.huanchengfly.tieba.post.widgets.ShadowLayout import com.huanchengfly.tieba.post.widgets.VideoPlayerStandard import com.scwang.smart.refresh.header.MaterialHeader @@ -37,10 +42,10 @@ import com.scwang.smart.refresh.layout.SmartRefreshLayout import retrofit2.Call import retrofit2.Callback import retrofit2.Response -import java.util.* -class PersonalizedFeedFragment : BaseFragment(), PersonalizedFeedAdapter.OnRefreshListener, Refreshable, Toolbar.OnMenuItemClickListener { - private var adapter: PersonalizedFeedAdapter? = null +class PersonalizedFeedFragment : BaseFragment(), PersonalizedFeedAdapter.OnRefreshListener, + Refreshable, Toolbar.OnMenuItemClickListener { + private val adapter: PersonalizedFeedAdapter by lazy { PersonalizedFeedAdapter(attachContext) } private var personalizedBean: PersonalizedBean? = null private var page = 1 @@ -85,9 +90,7 @@ class PersonalizedFeedFragment : BaseFragment(), PersonalizedFeedAdapter.OnRefre loadMore() } } - adapter = PersonalizedFeedAdapter(attachContext).apply { - onRefreshListener = this@PersonalizedFeedFragment - } + adapter.onRefreshListener = this recyclerView.apply { if (!appPreferences.loadPictureWhenScroll) { addOnScrollListener(object : RecyclerView.OnScrollListener() { @@ -98,10 +101,10 @@ class PersonalizedFeedFragment : BaseFragment(), PersonalizedFeedAdapter.OnRefre } if (newState == RecyclerView.SCROLL_STATE_IDLE) { Glide.with(attachContext) - .resumeRequests() + .resumeRequests() } else { Glide.with(attachContext) - .pauseRequests() + .pauseRequests() } } }) @@ -156,75 +159,103 @@ class PersonalizedFeedFragment : BaseFragment(), PersonalizedFeedAdapter.OnRefre fun refresh() { page = 1 - TiebaApi.getInstance().personalized(1, page).enqueue(object : Callback { - override fun onFailure(call: Call, t: Throwable) { - refreshLayout.finishRefresh(false) - if (t is TiebaException) { - Toast.makeText(attachContext, "${t.message}", Toast.LENGTH_SHORT).show() - } else { - Util.showNetworkErrorSnackbar(recyclerView) { refresh() } - return - } - } - - override fun onResponse(call: Call, response: Response) { - val personalizedBean = response.body()!! - this@PersonalizedFeedFragment.personalizedBean = personalizedBean - personalizedBean.threadList?.forEachIndexed { index, threadBean -> - threadBean.threadPersonalizedBean = personalizedBean.threadPersonalized?.get(index) - } - val newThreadBeans: List = personalizedBean.threadList?.filterNot { - (it.abstractBeans?.size!! > 0 && BlockUtil.needBlock(it.abstractBeans[0].text)) || BlockUtil.needBlock(it.author?.nameShow, it.author?.id) - }!! - val threadBeans: MutableList = ArrayList(adapter!!.allData) - adapter!!.apply { - if (dataCount > 0) { - refreshPosition = newThreadBeans.size - 1 + launchIO { + TiebaApi.getInstance().personalizedAsync(1, page) + .doIfSuccess { bean -> + personalizedBean = bean + bean.threadList?.forEachIndexed { index, threadBean -> + threadBean.threadPersonalizedBean = bean.threadPersonalized?.get(index) } - setNewData(if (threadBeans.addAll(0, newThreadBeans)) threadBeans else newThreadBeans) - } - refreshTipText.text = attachContext.getString(R.string.toast_feed_refresh, newThreadBeans.size) - AnimUtil.alphaIn(refreshTip) - .setListener(object : AnimatorListenerAdapter() { - override fun onAnimationEnd(animation: Animator) { - refreshTip.postDelayed({ - AnimUtil.alphaOut(refreshTip) - .setListener(object : AnimatorListenerAdapter() { - override fun onAnimationEnd(animation1: Animator) { - refreshTip.visibility = View.GONE - } - }) - .start() - }, 1500) + val newThreadBeans: List = + bean.threadList?.filterNot { + (it.abstractBeans?.size!! > 0 && BlockUtil.needBlock(it.abstractBeans[0].text)) || BlockUtil.needBlock( + it.author?.nameShow, + it.author?.id + ) + }!! + val threadBeans: MutableList = + ArrayList(adapter.getItemList()) + adapter.apply { + if (getItemList().isNotEmpty()) { + refreshPosition = newThreadBeans.size - 1 + } + setData( + if (threadBeans.addAll( + 0, + newThreadBeans + ) + ) threadBeans else newThreadBeans + ) + } + refreshTipText.text = + attachContext.getString(R.string.toast_feed_refresh, newThreadBeans.size) + animSet { + animator.interpolator = AccelerateDecelerateInterpolator() + anim { + values = intArrayOf(0, 100) + duration = 200 + action = { + refreshTip.alpha = it as Int / 100f } - }).start() - refreshLayout.finishRefresh(true) - } - }) + onStart = { + refreshTip.visibility = View.VISIBLE + } + } before anim { + values = intArrayOf(100, 0) + duration = 200 + action = { + refreshTip.alpha = it as Int / 100f + } + delay = 1500 + onEnd = { + refreshTip.visibility = View.GONE + } + } + }.start() + refreshLayout.finishRefresh(true) + } + .doIfFailure { + refreshLayout.finishRefresh(false) + if (it is TiebaException) { + Toast.makeText(attachContext, "${it.message}", Toast.LENGTH_SHORT).show() + } else { + Util.showNetworkErrorSnackbar(recyclerView) { refresh() } + } + } + } } private fun loadMore() { - TiebaApi.getInstance().personalized(2, page + 1).enqueue(object : Callback { - override fun onFailure(call: Call, t: Throwable) { - refreshLayout.finishLoadMore(false) - } + TiebaApi.getInstance().personalized(2, page + 1) + .enqueue(object : Callback { + override fun onFailure(call: Call, t: Throwable) { + refreshLayout.finishLoadMore(false) + } - override fun onResponse(call: Call, response: Response) { - val personalizedBean = response.body()!! - this@PersonalizedFeedFragment.personalizedBean = personalizedBean - personalizedBean.threadList?.forEachIndexed { index, threadBean -> - threadBean.threadPersonalizedBean = personalizedBean.threadPersonalized?.get(index) + override fun onResponse( + call: Call, + response: Response + ) { + val personalizedBean = response.body()!! + this@PersonalizedFeedFragment.personalizedBean = personalizedBean + personalizedBean.threadList?.forEachIndexed { index, threadBean -> + threadBean.threadPersonalizedBean = + personalizedBean.threadPersonalized?.get(index) + } + val newThreadBeans: List = + personalizedBean.threadList?.filterNot { + (it.abstractBeans?.size!! > 0 && BlockUtil.needBlock(it.abstractBeans[0].text)) || BlockUtil.needBlock( + it.author?.nameShow, + it.author?.id + ) + }!! + adapter.apply { + insert(newThreadBeans) + } + page += 1 + refreshLayout.finishLoadMore(true) } - val newThreadBeans: List = personalizedBean.threadList?.filterNot { - (it.abstractBeans?.size!! > 0 && BlockUtil.needBlock(it.abstractBeans[0].text)) || BlockUtil.needBlock(it.author?.nameShow, it.author?.id) - }!! - adapter!!.apply { - setLoadMoreData(newThreadBeans) - } - page += 1 - refreshLayout.finishLoadMore(true) - } - }) + }) } override fun onFragmentVisibleChange(isVisible: Boolean) {