fix: 修复一些空指针问题

This commit is contained in:
HuanCheng65 2022-06-16 09:24:43 +08:00
parent 9ffa9bbf21
commit 3ec9e823ee
No known key found for this signature in database
GPG Key ID: E9031EF91A805148
6 changed files with 171 additions and 96 deletions

View File

@ -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<PersonalizedBean.ThreadBean> {
public class PersonalizedFeedAdapter extends BaseMultiTypeAdapter<PersonalizedBean.ThreadBean> {
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<PersonalizedBean.T
}
private int getMaxWidth() {
int maxWidth = BaseApplication.ScreenInfo.EXACT_SCREEN_WIDTH - DisplayUtil.dp2px(mContext, 56);
if (ExtensionsKt.isTablet(mContext)) {
if (ExtensionsKt.isLandscape(mContext.getResources().getConfiguration())) {
int maxWidth = BaseApplication.ScreenInfo.EXACT_SCREEN_WIDTH - DisplayUtil.dp2px(getContext(), 56);
if (ExtensionsKt.isTablet(getContext())) {
if (ExtensionsKt.isLandscape(getContext().getResources().getConfiguration())) {
return maxWidth / 3;
} else {
return maxWidth / 2;
@ -108,7 +108,7 @@ public class PersonalizedFeedAdapter extends MultiBaseAdapter<PersonalizedBean.T
private void load(ForumPageBean.MediaInfoBean mediaInfoBean, ImageView imageView) {
imageView.setVisibility(View.VISIBLE);
String url = ImageUtil.getUrl(mContext, true, mediaInfoBean.getOriginPic(), mediaInfoBean.getSrcPic());
String url = ImageUtil.getUrl(getContext(), true, mediaInfoBean.getOriginPic(), mediaInfoBean.getSrcPic());
if ("3".equals(mediaInfoBean.getType())) {
ImageUtil.load(imageView, ImageUtil.LOAD_TYPE_NO_RADIUS, url);
}
@ -119,7 +119,7 @@ public class PersonalizedFeedAdapter extends MultiBaseAdapter<PersonalizedBean.T
}
@Override
protected void convert(ViewHolder viewHolder, PersonalizedBean.ThreadBean threadBean, int position, int viewType) {
protected void convert(MyViewHolder viewHolder, PersonalizedBean.ThreadBean threadBean, int position, int viewType) {
View refreshTip = viewHolder.getView(R.id.feed_refresh_tip);
if (position == getRefreshPosition()) {
refreshTip.setVisibility(View.VISIBLE);
@ -152,7 +152,7 @@ public class PersonalizedFeedAdapter extends MultiBaseAdapter<PersonalizedBean.T
}
remove(position);
} else {
DislikeDialog dislikeDialog = new DislikeDialog(mContext, threadBean.getThreadPersonalizedBean(), threadBean.getForumId());
DislikeDialog dislikeDialog = new DislikeDialog(getContext(), threadBean.getThreadPersonalizedBean(), threadBean.getForumId());
dislikeDialog.setOnSubmitListener(() -> {
if (position <= refreshPosition && refreshPosition > -1) {
refreshPosition -= 1;
@ -208,19 +208,19 @@ public class PersonalizedFeedAdapter extends MultiBaseAdapter<PersonalizedBean.T
}
PersonalizedBean.AuthorBean authorBean = threadBean.getAuthor();
if (authorBean != null) {
viewHolder.setOnClickListener(R.id.forum_item_user_avatar, v -> 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<PersonalizedBean.T
}
switch (viewType) {
case TYPE_THREAD_SINGLE_PIC:
if (Util.canLoadGlide(mContext) && "3".equals(threadBean.getMedia().get(0).getType())) {
if (Util.canLoadGlide(getContext()) && "3".equals(threadBean.getMedia().get(0).getType())) {
ImageView imageView = viewHolder.getView(R.id.forum_item_content_pic);
imageView.setLayoutParams(getLayoutParams((RelativeLayout.LayoutParams) imageView.getLayoutParams()));
setListenerForImageView(threadBean.getMedia(), imageView, 0);
@ -236,14 +236,14 @@ public class PersonalizedFeedAdapter extends MultiBaseAdapter<PersonalizedBean.T
ImageUtil.load(
imageView,
ImageUtil.LOAD_TYPE_SMALL_PIC,
ImageUtil.getUrl(mContext, true, mediaInfoBean.getOriginPic(), mediaInfoBean.getSrcPic())
ImageUtil.getUrl(getContext(), true, mediaInfoBean.getOriginPic(), mediaInfoBean.getSrcPic())
);
}
break;
case TYPE_THREAD_MULTI_PIC:
GridLayout gridLayout = viewHolder.getView(R.id.forum_item_content_pics);
CardView cardView = viewHolder.getView(R.id.forum_item_content_pics_card);
cardView.setRadius(DisplayUtil.dp2px(mContext, SharedPreferencesUtil.get(mContext, SharedPreferencesUtil.SP_SETTINGS).getInt("radius", 8)));
cardView.setRadius(DisplayUtil.dp2px(getContext(), SharedPreferencesUtil.get(getContext(), SharedPreferencesUtil.SP_SETTINGS).getInt("radius", 8)));
MarkedImageView firstImageView = viewHolder.getView(R.id.forum_item_content_pic_1);
MarkedImageView secondImageView = viewHolder.getView(R.id.forum_item_content_pic_2);
MarkedImageView thirdImageView = viewHolder.getView(R.id.forum_item_content_pic_3);
@ -255,7 +255,7 @@ public class PersonalizedFeedAdapter extends MultiBaseAdapter<PersonalizedBean.T
load(firstMedia, firstImageView);
} else {
firstImageView.setVisibility(View.GONE);
Glide.with(mContext)
Glide.with(getContext())
.clear(firstImageView);
}
if (size >= 2) {
@ -264,7 +264,7 @@ public class PersonalizedFeedAdapter extends MultiBaseAdapter<PersonalizedBean.T
load(secondMedia, secondImageView);
} else {
secondImageView.setVisibility(View.GONE);
Glide.with(mContext)
Glide.with(getContext())
.clear(secondImageView);
}
if (size >= 3) {
@ -273,7 +273,7 @@ public class PersonalizedFeedAdapter extends MultiBaseAdapter<PersonalizedBean.T
load(thirdMedia, thirdImageView);
} else {
thirdImageView.setVisibility(View.GONE);
Glide.with(mContext)
Glide.with(getContext())
.clear(thirdImageView);
}
if (size > 3) {

View File

@ -186,12 +186,12 @@ class ThreadMainPostAdapter(
}
val forumNameView = forumView.findViewById<TextView>(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)
}

View File

@ -27,6 +27,17 @@ interface ITiebaApi {
page: Int = 1
): Call<PersonalizedBean>
/**
* 个性推荐每页 15
*
* @param loadType 加载类型1 - 下拉刷新 2 - 加载更多
* @param page 分页页码
*/
fun personalizedAsync(
loadType: Int,
page: Int = 1
): Deferred<ApiResult<PersonalizedBean>>
/**
* 给贴子/回复点赞
*

View File

@ -30,6 +30,12 @@ object MixedTiebaApiImpl : ITiebaApi {
override fun personalized(loadType: Int, page: Int): Call<PersonalizedBean> =
RetrofitTiebaApi.MINI_TIEBA_API.personalized(loadType, page)
override fun personalizedAsync(
loadType: Int,
page: Int
): Deferred<ApiResult<PersonalizedBean>> =
RetrofitTiebaApi.MINI_TIEBA_API.personalizedAsync(loadType, page)
override fun myProfileAsync(): Deferred<ApiResult<Profile>> =
RetrofitTiebaApi.WEB_TIEBA_API.myProfileAsync("json", "", "")

View File

@ -42,6 +42,33 @@ interface MiniTiebaApi {
@Field("scr_w") scr_w: String = getScreenWidth().toString()
): Call<PersonalizedBean>
@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<ApiResult<PersonalizedBean>>
@Headers("${Header.FORCE_LOGIN}: ${Header.FORCE_LOGIN_TRUE}")
@POST("/c/c/agree/opAgree")
@FormUrlEncoded

View File

@ -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<PersonalizedBean> {
override fun onFailure(call: Call<PersonalizedBean>, 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<PersonalizedBean>, response: Response<PersonalizedBean>) {
val personalizedBean = response.body()!!
this@PersonalizedFeedFragment.personalizedBean = personalizedBean
personalizedBean.threadList?.forEachIndexed { index, threadBean ->
threadBean.threadPersonalizedBean = personalizedBean.threadPersonalized?.get(index)
}
val newThreadBeans: List<PersonalizedBean.ThreadBean> = personalizedBean.threadList?.filterNot {
(it.abstractBeans?.size!! > 0 && BlockUtil.needBlock(it.abstractBeans[0].text)) || BlockUtil.needBlock(it.author?.nameShow, it.author?.id)
}!!
val threadBeans: MutableList<PersonalizedBean.ThreadBean> = 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<PersonalizedBean.ThreadBean> =
bean.threadList?.filterNot {
(it.abstractBeans?.size!! > 0 && BlockUtil.needBlock(it.abstractBeans[0].text)) || BlockUtil.needBlock(
it.author?.nameShow,
it.author?.id
)
}!!
val threadBeans: MutableList<PersonalizedBean.ThreadBean> =
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<PersonalizedBean> {
override fun onFailure(call: Call<PersonalizedBean>, t: Throwable) {
refreshLayout.finishLoadMore(false)
}
TiebaApi.getInstance().personalized(2, page + 1)
.enqueue(object : Callback<PersonalizedBean> {
override fun onFailure(call: Call<PersonalizedBean>, t: Throwable) {
refreshLayout.finishLoadMore(false)
}
override fun onResponse(call: Call<PersonalizedBean>, response: Response<PersonalizedBean>) {
val personalizedBean = response.body()!!
this@PersonalizedFeedFragment.personalizedBean = personalizedBean
personalizedBean.threadList?.forEachIndexed { index, threadBean ->
threadBean.threadPersonalizedBean = personalizedBean.threadPersonalized?.get(index)
override fun onResponse(
call: Call<PersonalizedBean>,
response: Response<PersonalizedBean>
) {
val personalizedBean = response.body()!!
this@PersonalizedFeedFragment.personalizedBean = personalizedBean
personalizedBean.threadList?.forEachIndexed { index, threadBean ->
threadBean.threadPersonalizedBean =
personalizedBean.threadPersonalized?.get(index)
}
val newThreadBeans: List<PersonalizedBean.ThreadBean> =
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.ThreadBean> = 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) {