Merge branch 'sync_page_data'

This commit is contained in:
kehaoyuan@ghzhushou.com
2020-03-24 16:49:39 +08:00
17 changed files with 506 additions and 3 deletions

View File

@ -19,6 +19,9 @@ import androidx.fragment.app.FragmentTransaction;
import com.gh.base.OnListClickListener;
import com.gh.base.OnRequestCallBackListener;
import com.gh.common.constant.Constants;
import com.gh.common.syncpage.ISyncAdapterHandler;
import com.gh.common.syncpage.SyncDataEntity;
import com.gh.common.syncpage.SyncPageRepository;
import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.eventbus.EBMiPush;
import com.lightgame.OnTitleClickListener;
@ -32,10 +35,18 @@ import org.greenrobot.eventbus.ThreadMode;
import java.lang.ref.WeakReference;
import java.util.List;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import androidx.recyclerview.widget.RecyclerView;
import butterknife.ButterKnife;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import kotlin.Pair;
import static com.gh.common.util.EntranceUtils.KEY_ENTRANCE;
@ -142,6 +153,36 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
ButterKnife.bind(this, mCachedView);
initView(mCachedView);
if (addSyncPageObserver()) {
initSyncPageObserver();
}
}
private void initSyncPageObserver() {
SyncPageRepository.INSTANCE.getSyncPageLiveData().observe(this, syncDataEntities -> {
try {
if (syncDataEntities == null || syncDataEntities.isEmpty()) return;
RecyclerView.Adapter adapter = provideSyncAdapter();
if (!(adapter instanceof ISyncAdapterHandler)) return;
for (int i = 0; i < adapter.getItemCount(); i++) {
Pair<String, Object> syncKey = ((ISyncAdapterHandler) adapter).getSyncData(i);
if (syncKey == null) return;
for (SyncDataEntity syncDataEntity : syncDataEntities) {
if (syncDataEntity.getSyncId().equals(syncKey.getFirst())) {
boolean isSuccess = SyncPageRepository.INSTANCE.handleSyncData(syncKey.getSecond(), syncDataEntity);
if (isSuccess) adapter.notifyItemChanged(i);
}
}
}
} catch (Exception e) {
if (BuildConfig.DEBUG) {
throw e;
} else {
e.printStackTrace();
}
}
});
}
// 必须的有subscribe才能register
@ -252,4 +293,12 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
return this;
}
@Nullable
protected RecyclerView.Adapter provideSyncAdapter() {
return null;
}
protected boolean addSyncPageObserver() {
return false;
}
}

View File

@ -0,0 +1,12 @@
package com.gh.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SyncPage {
String[] syncNames();
}

View File

@ -0,0 +1,12 @@
package com.gh.common.syncpage
interface ISyncAdapterHandler {
/**
* @param position position to query
* @return Pair first: item sync id
* Pair second: item data entity
*/
fun getSyncData(position: Int): Pair<String, Any>?
}

View File

@ -0,0 +1,43 @@
package com.gh.common.syncpage
import androidx.annotation.Keep
@Keep
data class SyncDataEntity(
/**
* 标识一条数据的唯一ID
*
* 与[ISyncAdapterHandler.getSyncData]返回的Pair first一致
*/
val syncId: String,
/**
* 需要同步的字段名
*
* 与@SyncPage注解的值一致
*/
val syncFieldName: String?,
/**
* 需要同步的具体内容
*/
val syncFieldValue: Any?,
/**
* 同步完一次是否自动删除
*/
val remove: Boolean = true,
/**
* 是否需要查询同步实体的父级字段
*
* 由于反射可能会导致较大的性能消耗,默认关闭,具体按实际情况开启
*/
val checkInherited: Boolean = false,
/**
* 是否需要查询同步实体的嵌套实体内容
*
* 由于反射可能会导致较大的性能消耗,默认关闭,具体按实际情况开启
*/
val checkFieldEntity: Boolean = false)

View File

@ -0,0 +1,17 @@
package com.gh.common.syncpage
object SyncFieldConstants {
// 是否点赞
const val ANSWER_VOTE = "ANSWER_VOTE"
const val ARTICLE_VOTE = "ARTICLE_VOTE"
// 赞同数量
const val ANSWER_VOTE_COUNT = "ANSWER_VOTE_COUNT"
const val ARTICLE_VOTE_COUNT = "ARTICLE_VOTE_COUNT"
// 评论数量
const val ANSWER_COMMENT_COUNT = "ANSWER_COMMENT_COUNT"
const val ARTICLE_COMMENT_COUNT = "ARTICLE_COMMENT_COUNT"
}

View File

@ -0,0 +1,116 @@
package com.gh.common.syncpage
import androidx.lifecycle.MutableLiveData
import com.gh.common.annotation.SyncPage
import com.gh.common.util.toJson
import com.gh.common.util.tryCatchInRelease
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import java.lang.reflect.Field
import java.util.concurrent.CopyOnWriteArrayList
/**
* 页面之间实现数据同步(主要是单个字段的同步)
*
* 实现思路:
* 1.把需要同步的数据以一个特殊ID作为唯一标识并存于一个全局的仓库
* 2.利用LiveData进行页面回调,再通过[ISyncAdapterHandler.getSyncData]找到需要被同步的数据
* 3.最后利用反射进行数据替换,具体请见[SyncPageRepository.replaceSyncData]
*
* 具体的接入方式(以列表为例)
* 1.通过[SyncPageRepository.postSyncData]提交同步数据
* 2.在Fragment重写[BaseFragment.addSyncPageObserver]开启同步事件监听
* 3.在Fragment重写[BaseFragment.provideSyncAdapter]提供获取数据的来源
* - [BaseFragment.provideSyncAdapter]提供的Adapter必须实现[ISyncAdapterHandler]接口
*/
object SyncPageRepository {
// 只有在新增操作时,才需要进行页面刷新
val syncPageLiveData = MutableLiveData<List<SyncDataEntity>>()
val syncDataList = CopyOnWriteArrayList<SyncDataEntity>()
@JvmStatic
fun clearSyncData() {
tryCatchInRelease {
syncDataList.clear()
}
}
// 提交同步数据
fun postSyncData(entity: SyncDataEntity) {
tryCatchInRelease {
// 检查是否存在重复操作
for (syncDataEntity in syncDataList) {
if (syncDataEntity.syncId == entity.syncId && syncDataEntity.syncFieldName == entity.syncFieldName) {
syncDataList.remove(syncDataEntity)
syncDataList.add(entity)
return
}
}
syncDataList.add(entity)
syncPageLiveData.postValue(syncDataList)
Utils.log("SyncPageRepository postSyncData->" + entity.toJson())
}
}
fun handleSyncData(rawData: Any, syncData: SyncDataEntity): Boolean {
val fields = if (syncData.checkInherited) {
getAllFieldsList(rawData::class.java)
} else rawData::class.java.declaredFields.toList()
var isNeedNotify = false
for (field in fields) {
isNeedNotify = replaceSyncData(field, rawData, syncData)
if (isNeedNotify) break
}
if (syncData.remove) syncDataList.remove(syncData)
if (!isNeedNotify) {
Utils.log("SyncPageRepository sync failure-> " + syncData.syncFieldName)
} else {
Utils.log("SyncPageRepository sync success-> " + syncData.syncFieldName)
}
return isNeedNotify
}
private fun replaceSyncData(field: Field, extractObject: Any, syncData: SyncDataEntity): Boolean {
field.getAnnotation(SyncPage::class.java)?.syncNames?.forEach { syncName ->
if (syncName == syncData.syncFieldName) {
field.isAccessible = true
field.set(extractObject, syncData.syncFieldValue)
return true
}
}
if (syncData.checkFieldEntity) {
// 递归查询
val pkgName = field.type.getPackage()?.name ?: return false
if (pkgName.contains(HaloApp.getInstance().application.packageName)) {
field.isAccessible = true
val extractEntityObject = field.get(extractObject) ?: return false
field.type.declaredFields.forEach {
if (replaceSyncData(it, extractEntityObject, syncData)) return true
}
}
}
return false
}
// 包括父类 Field 对象
private fun getAllFieldsList(cls: Class<*>?): List<Field> {
if (cls == null) return arrayListOf()
val allFields = arrayListOf<Field>()
var currentClass = cls
while (currentClass != null) {
val declaredFields = currentClass.declaredFields
allFields.addAll(declaredFields)
currentClass = currentClass.superclass
}
return allFields
}
}

View File

@ -0,0 +1,98 @@
package com.gh.common.syncpage.example
import android.content.Context
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.constant.ItemViewType
import com.gh.common.syncpage.ISyncAdapterHandler
import com.gh.gamecenter.R
import com.gh.gamecenter.adapter.viewholder.FooterViewHolder
import com.gh.gamecenter.baselist.ListAdapter
import com.gh.gamecenter.databinding.CommunityAnswerItemBinding
import com.gh.gamecenter.manager.UserManager
import com.gh.gamecenter.qa.answer.CommunityAnswerItemViewHolder
import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity
import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
import com.gh.gamecenter.qa.entity.AnswerEntity
import com.gh.gamecenter.qa.entity.Questions
import com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity
class ExampleAdapter(context: Context) : ListAdapter<AnswerEntity>(context), ISyncAdapterHandler {
override fun areItemsTheSame(oldItem: AnswerEntity?, newItem: AnswerEntity?): Boolean {
return oldItem?.id == newItem?.id
}
override fun getItemViewType(position: Int): Int {
if (position == itemCount - 1) return ItemViewType.ITEM_FOOTER
return ItemViewType.ITEM_BODY
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view: View
return when (viewType) {
ItemViewType.ITEM_FOOTER -> {
view = mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false)
FooterViewHolder(view)
}
else -> {
view = mLayoutInflater.inflate(R.layout.community_answer_item, parent, false)
CommunityAnswerItemViewHolder(CommunityAnswerItemBinding.bind(view))
}
}
}
override fun getItemCount(): Int {
return if (mEntityList.isNotEmpty()) mEntityList.size + FOOTER_ITEM_COUNT else 0
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (getItemViewType(position)) {
ItemViewType.ITEM_BODY -> {
val answer = mEntityList[position]
if ("community_article" == answer.type) {
val questions = Questions()
questions.title = answer.articleTitle
answer.questions = questions
}
val answerViewHolder = holder as CommunityAnswerItemViewHolder
val binding = answerViewHolder.binding
answerViewHolder.bindAnswerItem(answer, "", getPath())
binding.title.setOnClickListener {
if ("community_article" == answer.type) {
mContext.startActivity(ArticleDetailActivity.getIntent(mContext, UserManager.getInstance().community, answer.id!!, "", getPath()))
} else {
val questions = answer.questions
mContext.startActivity(QuestionsDetailActivity.getIntent(mContext, questions.id, "", getPath()))
}
}
answerViewHolder.itemView.setOnClickListener {
if ("community_article" == answer.type) {
mContext.startActivity(ArticleDetailActivity.getIntent(mContext, UserManager.getInstance().community, answer.id!!, "", getPath()))
} else {
mContext.startActivity(AnswerDetailActivity.getIntent(mContext, answer.id, "", getPath()))
}
}
}
ItemViewType.ITEM_FOOTER -> {
val footerViewHolder = holder as FooterViewHolder
footerViewHolder.initItemPadding()
footerViewHolder.initFooterViewHolder(mIsLoading, mIsNetworkError, mIsOver, R.string.ask_loadover_hint)
}
}
}
override fun getSyncData(position: Int): Pair<String, AnswerEntity>? {
if (position >= mEntityList.size) return null
val entity = mEntityList[position]
return Pair(entity.id ?: "", entity)
}
fun getPath(): String {
return "问答-推荐-按时间"
}
}

View File

@ -0,0 +1,65 @@
package com.gh.common.syncpage.example
import android.os.Bundle
import android.view.View
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.view.VerticalItemDecoration
import com.gh.gamecenter.baselist.ListFragment
import com.gh.gamecenter.baselist.NormalListViewModel
import com.gh.gamecenter.manager.UserManager
import com.gh.gamecenter.qa.entity.AnswerEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.Observable
class ExampleFragment : ListFragment<AnswerEntity, NormalListViewModel<AnswerEntity>>() {
private var mAdapter: ExampleAdapter? = null
override fun provideListAdapter(): ExampleAdapter {
if (mAdapter == null) {
mAdapter = ExampleAdapter(requireContext())
}
return mAdapter!!
}
override fun getItemDecoration(): RecyclerView.ItemDecoration {
return VerticalItemDecoration(context, 8F, false)
}
override fun provideDataObservable(page: Int): Observable<MutableList<AnswerEntity>> {
return RetrofitManager.getInstance(context).api.getCommunitiesRecommendNewest(UserManager.getInstance().community.id, page)
}
override fun provideListViewModel(): NormalListViewModel<AnswerEntity> {
val factory = NormalListViewModel.Factory(HaloApp.getInstance().application, this)
return ViewModelProviders.of(this, factory).get(NormalListViewModel::class.java) as NormalListViewModel<AnswerEntity>
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// SyncPageRepository.syncPageLiveData.observe(this, Observer {
// it ?: return@Observer
// val adapter = mListRv.adapter
// if (adapter !is ISyncAdapterHandler) return@Observer
// for(position in 0 until adapter.itemCount) {
// val syncKey = adapter.getSyncData(position)
// for (syncDataEntity in it) {
// if (syncDataEntity.syncId == syncKey?.first) {
// val isSuccess = SyncPageRepository.handleSyncData(syncKey.second, syncDataEntity)
// if (isSuccess) adapter.notifyItemChanged(position)
// }
// }
// }
// })
}
override fun provideSyncAdapter(): RecyclerView.Adapter<*>? {
return mListRv.adapter
}
override fun addSyncPageObserver(): Boolean {
return true
}
}

View File

@ -1,6 +1,8 @@
package com.gh.gamecenter.entity
import android.os.Parcelable
import com.gh.common.annotation.SyncPage
import com.gh.common.syncpage.SyncFieldConstants
import com.google.gson.annotations.SerializedName
import kotlinx.android.parcel.Parcelize
@ -14,6 +16,7 @@ class MeEntity(@SerializedName("is_community_voted")
@SerializedName("is_user_invite")
var isUserInvite: Boolean = false,
@SyncPage(syncNames = [SyncFieldConstants.ANSWER_VOTE])
@SerializedName("is_answer_voted")
var isAnswerVoted: Boolean = false,
@ -50,10 +53,10 @@ class MeEntity(@SerializedName("is_community_voted")
@SerializedName("is_toolkit_favorite")
var isToolkitFavorite: Boolean = false,
@SerializedName("is_comment_own", alternate = ["is_answer_commented", "is_community_article_commented", "is_video_commented"])
@SerializedName("is_comment_own", alternate = ["is_answer_commented", "is_community_article_commented", "is_video_commented"])
var isCommentOwner: Boolean = false, // 是否是当前评论的拥有者
@SerializedName("is_comment_voted", alternate = ["is_answer_comment_voted","is_video_comment_voted", "is_community_article_comment_voted"])
@SerializedName("is_comment_voted", alternate = ["is_answer_comment_voted", "is_video_comment_voted", "is_community_article_comment_voted"])
var isCommentVoted: Boolean = false, // 是否已经点赞过当前评论
@SerializedName("is_version_requested")
@ -65,6 +68,7 @@ class MeEntity(@SerializedName("is_community_voted")
@SerializedName("is_favorite")
var isCommunityArticleFavorite: Boolean = false,
@SyncPage(syncNames = [SyncFieldConstants.ARTICLE_VOTE])
@SerializedName("is_vote")
var isCommunityArticleVote: Boolean = false,

View File

@ -26,6 +26,7 @@ import com.facebook.imagepipeline.image.ImageInfo;
import com.gh.base.OnDoubleTapListener;
import com.gh.base.fragment.BaseFragment_ViewPager_Checkable;
import com.gh.common.constant.Config;
import com.gh.common.syncpage.SyncPageRepository;
import com.gh.common.util.DataUtils;
import com.gh.common.util.DisplayUtils;
import com.gh.common.util.EntranceUtils;
@ -264,6 +265,10 @@ public class MainWrapperFragment extends BaseFragment_ViewPager_Checkable implem
super.onResume();
//mViewModel.getDiscoveryData(false);
MessageUnreadRepository.INSTANCE.loadMessageUnreadTotal();
if (isEverPause) {
mBaseHandler.postDelayed(SyncPageRepository::clearSyncData, 2000);
}
}
@Override

View File

@ -6,6 +6,9 @@ import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.gh.common.history.HistoryHelper
import com.gh.common.syncpage.SyncDataEntity
import com.gh.common.syncpage.SyncFieldConstants
import com.gh.common.syncpage.SyncPageRepository
import com.gh.common.util.*
import com.gh.gamecenter.R
import com.gh.gamecenter.entity.SpecialColumn
@ -88,6 +91,8 @@ class AnswerDetailViewModel(application: Application) : AndroidViewModel(applica
val apiResponse = ApiResponse<VoteEntity>()
apiResponse.data = response
mVoteLiveData.postValue(apiResponse)
syncVoteData(answerId)
}
override fun onFailure(e: HttpException?) {
@ -111,6 +116,8 @@ class AnswerDetailViewModel(application: Application) : AndroidViewModel(applica
val apiResponse = ApiResponse<VoteEntity>()
apiResponse.data = response
mVoteLiveData.postValue(apiResponse)
syncVoteData(answerId)
}
override fun onFailure(e: HttpException?) {
@ -134,6 +141,8 @@ class AnswerDetailViewModel(application: Application) : AndroidViewModel(applica
answerDetail?.me?.isAnswerVoted = false
dislike.postValue(true)
syncVoteData(answerId)
}
override fun onFailure(e: HttpException?) {
@ -150,6 +159,8 @@ class AnswerDetailViewModel(application: Application) : AndroidViewModel(applica
override fun onResponse(response: ResponseBody?) {
answerDetail?.me?.isAnswerOpposed = false
dislike.postValue(false)
syncVoteData(answerId)
}
override fun onFailure(e: HttpException?) {
@ -158,6 +169,16 @@ class AnswerDetailViewModel(application: Application) : AndroidViewModel(applica
})
}
private fun syncVoteData(answerId: String) {
SyncPageRepository.postSyncData(SyncDataEntity(answerId,
SyncFieldConstants.ANSWER_VOTE_COUNT,
answerDetail!!.vote))
SyncPageRepository.postSyncData(SyncDataEntity(answerId,
SyncFieldConstants.ANSWER_VOTE,
answerDetail?.me?.isAnswerVoted,
checkFieldEntity = true))
}
fun collectAnswer(answerId: String) {
CollectionUtils.postCollection(getApplication(), answerId, CollectionUtils.CollectionType.answer, object : CollectionUtils.OnCollectionListener {
override fun onSuccess() {

View File

@ -5,6 +5,7 @@ import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.constant.ItemViewType
import com.gh.common.syncpage.ISyncAdapterHandler
import com.gh.gamecenter.R
import com.gh.gamecenter.adapter.viewholder.FooterViewHolder
import com.gh.gamecenter.baselist.ListAdapter
@ -15,7 +16,7 @@ import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
import com.gh.gamecenter.qa.entity.ArticleEntity
import com.gh.gamecenter.qa.entity.Questions
class SimpleArticleListAdapter(context: Context) : ListAdapter<ArticleEntity>(context) {
class SimpleArticleListAdapter(context: Context) : ListAdapter<ArticleEntity>(context), ISyncAdapterHandler {
override fun areItemsTheSame(oldItem: ArticleEntity?, newItem: ArticleEntity?): Boolean {
return oldItem?.id == newItem?.id
@ -72,4 +73,10 @@ class SimpleArticleListAdapter(context: Context) : ListAdapter<ArticleEntity>(co
}
}
override fun getSyncData(position: Int): Pair<String, Any>? {
if (position >= mEntityList.size) return null
val entity = mEntityList[position]
return Pair(entity.id, entity)
}
}

View File

@ -86,4 +86,12 @@ class SimpleArticleListFragment : ListFragment<ArticleEntity, SimpleArticleListV
mBaseHandler.postDelayed({ mListViewModel.load(LoadType.REFRESH) }, 100)
}
}
override fun provideSyncAdapter(): RecyclerView.Adapter<*>? {
return mAdapter
}
override fun addSyncPageObserver(): Boolean {
return true
}
}

View File

@ -4,6 +4,9 @@ import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.gh.common.syncpage.SyncDataEntity
import com.gh.common.syncpage.SyncFieldConstants
import com.gh.common.syncpage.SyncPageRepository
import com.gh.common.util.CollectionUtils
import com.gh.common.util.ErrorHelper
import com.gh.gamecenter.R
@ -79,6 +82,8 @@ class ArticleDetailViewModel(application: Application) : AndroidViewModel(applic
detailEntity!!.count.vote--
like.postValue(response)
syncVoteData()
}
override fun onFailure(e: HttpException?) {
@ -99,6 +104,8 @@ class ArticleDetailViewModel(application: Application) : AndroidViewModel(applic
detailEntity!!.count.vote++
like.postValue(response)
syncVoteData()
}
override fun onFailure(e: HttpException?) {
@ -119,6 +126,8 @@ class ArticleDetailViewModel(application: Application) : AndroidViewModel(applic
detailEntity?.me?.isCommunityArticleVote = false
dislike.postValue(true)
syncVoteData()
}
override fun onFailure(e: HttpException?) {
@ -135,6 +144,8 @@ class ArticleDetailViewModel(application: Application) : AndroidViewModel(applic
detailEntity?.me?.isCommunityArticleOppose = false
dislike.postValue(false)
syncVoteData()
}
override fun onFailure(e: HttpException?) {
@ -143,6 +154,19 @@ class ArticleDetailViewModel(application: Application) : AndroidViewModel(applic
})
}
private fun syncVoteData() {
articleId?.apply {
SyncPageRepository.postSyncData(SyncDataEntity(this,
SyncFieldConstants.ARTICLE_VOTE_COUNT,
detailEntity?.count?.vote,
checkFieldEntity = true))
SyncPageRepository.postSyncData(SyncDataEntity(this,
SyncFieldConstants.ARTICLE_VOTE,
detailEntity?.me?.isCommunityArticleVote,
checkFieldEntity = true))
}
}
fun collectionCommand(isCollection: Boolean, callback: (isFollow: Boolean) -> Unit) {
val observable = if (isCollection) {
mApi.postCommunityArticleFavorites(UserManager.getInstance().userId, community?.id, articleId)

View File

@ -21,6 +21,9 @@ import butterknife.BindView
import butterknife.OnClick
import butterknife.Optional
import com.gh.base.fragment.BaseDialogWrapperFragment
import com.gh.common.syncpage.SyncDataEntity
import com.gh.common.syncpage.SyncFieldConstants
import com.gh.common.syncpage.SyncPageRepository
import com.gh.common.util.*
import com.gh.common.view.VerticalItemDecoration
import com.gh.gamecenter.R
@ -93,6 +96,17 @@ open class NewCommentFragment : ListFragment<CommentEntity, NewCommentViewModel>
mCommentListener?.onCommentDraftChange("")
}
commentEt.postDelayed({ setSoftInput(false) }, 100)
if (mCommentType == CommentType.COMMUNITY_ARTICLE) {
SyncPageRepository.postSyncData(SyncDataEntity(mArticleId,
SyncFieldConstants.ARTICLE_COMMENT_COUNT,
mCommentCount,
checkFieldEntity = true))
} else if (mCommentType == CommentType.ANSWER) {
SyncPageRepository.postSyncData(SyncDataEntity(mAnswerId,
SyncFieldConstants.ANSWER_COMMENT_COUNT,
mCommentCount))
}
}
apiResponse.httpException != null -> {
mSendingDialog?.dismiss()

View File

@ -7,6 +7,8 @@ import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey
import androidx.room.TypeConverters
import com.gh.common.annotation.SyncPage
import com.gh.common.syncpage.SyncFieldConstants
import com.gh.gamecenter.entity.MeEntity
import com.gh.gamecenter.entity.UserEntity
import com.gh.gamecenter.room.converter.AnswerUserConverter
@ -47,6 +49,7 @@ class AnswerEntity() : Parcelable {
@TypeConverters(CommunityVideoConverter::class)
var videos: List<CommunityVideoEntity> = ArrayList()
@SyncPage(syncNames = [SyncFieldConstants.ANSWER_VOTE_COUNT, SyncFieldConstants.ARTICLE_VOTE_COUNT])
var vote: Int = 0
@TypeConverters(AnswerUserConverter::class)
@ -59,6 +62,7 @@ class AnswerEntity() : Parcelable {
@SerializedName("community_name")
var communityName: String? = null
@SyncPage(syncNames = [SyncFieldConstants.ANSWER_COMMENT_COUNT, SyncFieldConstants.ARTICLE_COMMENT_COUNT])
@SerializedName("comment_count")
var commentCount: Int = 0

View File

@ -5,6 +5,8 @@ import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey
import androidx.room.TypeConverters
import com.gh.common.annotation.SyncPage
import com.gh.common.syncpage.SyncFieldConstants
import com.gh.gamecenter.entity.CommunityEntity
import com.gh.gamecenter.entity.MeEntity
import com.gh.gamecenter.entity.UserEntity
@ -69,7 +71,9 @@ data class ArticleEntity(
@Parcelize
data class Count(
@SyncPage(syncNames = [SyncFieldConstants.ARTICLE_COMMENT_COUNT])
var comment: Int = 0,
@SyncPage(syncNames = [SyncFieldConstants.ARTICLE_VOTE_COUNT])
var vote: Int = 0,
var answer: Int = 0) : Parcelable