Не удается сохранить состояние значка при обновлении представления переработчика - PullRequest
0 голосов
/ 13 февраля 2019

У меня есть какое-то новостное приложение, и я загружаю новости с модификацией и помещаю их в представление переработчика.Я использую rxjava для нумерации страниц и комнату для сохранения новостей в базу данных комнаты.Вот как это выглядит: https://imgur.com/a/7TbQn4C

Когда я нажимаю на значок сохранения, он должен сменить значок как здесь https://imgur.com/a/nndEfdB

и сохранить эти новости в БД.И он изменил значок и сохранил новости, но он сохранил другие новости, а не то, что он должен сохранять https://imgur.com/a/cLRrDvE

И когда я продолжаю прокручивать, чтобы получать больше новостей, я обнаруживаю, что все значки пришли впервое состояние, как на первом рисунке, но это не правильная новость все еще в БД.Итак, у меня есть два вопроса: 1. Как я могу сохранить состояние значка 2. Как я могу сохранить новости, которые мне нужны

Это мой код адаптера представления переработчика (здесь я слушаю изображение, нажимаю и сохраняю его в БД)

package com.hfad.cointask.adapter

import android.content.Context
import android.content.Intent
import android.graphics.drawable.TransitionDrawable
import android.util.Log
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.AnimationUtils
import android.widget.ImageView
import android.widget.TextView
import com.hfad.cointask.R
import com.hfad.cointask.helper.AppDatabase
import com.hfad.cointask.helper.CallableNews
import com.hfad.cointask.model.News
import com.hfad.cointask.service.ItemClickListener
import com.squareup.picasso.Picasso
import io.reactivex.Completable
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import java.util.*
import java.util.function.Consumer


@Suppress("DEPRECATION")
class CoinAdapter(var values: List<News>, var context: Context): androidx.recyclerview.widget.RecyclerView.Adapter<CoinAdapter.CoinViewHolder>() {

    val intent = Intent(context, NewsViewActivity::class.java)

    lateinit var item: News

    var db:AppDatabase = AppDatabase.getInstance(context) as AppDatabase
    private var compositeDispossable: CompositeDisposable = CompositeDisposable()

    object NewsFields {
        var title = ""
        var id = ""
        var newsThumb = ""
        var label: String? = ""
    }


    override fun onBindViewHolder(p0: CoinViewHolder, p1: Int) {


        item = values[p1]

        NewsFields.title = item.getTitle()
        p0.newsTitle.text = NewsFields.title

        NewsFields.id = item.getId().toString()
        val idItem = NewsFields.id

        NewsFields.label = item.getBadge()?.getLabel()
        val labelItem = NewsFields.label

        NewsFields.newsThumb = item.getThumb()
        val thumbItem = NewsFields.newsThumb



        if (labelItem == "default") {

            p0.newsThumb.setImageDrawable(null)

            } else {
            p0.newsThumb.visibility = View.VISIBLE
            Picasso.get()
                    .load(thumbItem)
                    .into(p0.newsThumb)
        }

        p0.setItemClickListener(object: ItemClickListener {
            override fun onClick(v: View, position: Int, isLongClick: Boolean) {

                intent.putExtra("id", idItem)
                context.startActivity(intent)

            }

        })

        setOnImageClickListener(p0.saveNews)


    }

    override fun getItemCount(): Int {

        return values.size

    }

    fun saveToDb(data: News, db: AppDatabase) {

        Completable.fromAction{ db.newsDao().insert(data) }
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({}, {
                    Log.d("SaveToDb", "Again", it)
                })

    }

    fun deleteFromDb(data: News, db: AppDatabase) {

        Completable.fromAction{ db.newsDao().delete(data) }
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({}, {
                    Log.d("SaveToDb", "Again", it)
                })

    }


    private fun setOnImageClickListener(img: ImageView) {

        img.setOnClickListener {
            if (img.tag == "saved") {
                img.setImageResource(R.drawable.save_icon_outline_24)
                img.tag = "not saved"
                deleteFromDb(item, db)
            } else {
                img.setImageResource(R.drawable.save_icon_24)
                img.tag = "saved"
                saveToDb(item, db)
            }

        }

        img.setOnLongClickListener {
            img.setImageResource(R.drawable.save_icon_24)
             true
        }

    }

    override fun onCreateViewHolder(p0: ViewGroup, p1: Int): CoinViewHolder {

        val view: View = LayoutInflater.from(p0.context).inflate(R.layout.news_item_view, p0, false)
        return CoinViewHolder(view)

    }


    class CoinViewHolder(itemView: View): ViewHolder(itemView), View.OnLongClickListener, View.OnClickListener {

        private lateinit var itemClickListener:ItemClickListener
        lateinit var transition: TransitionDrawable

        fun setItemClickListener(itemClickListener: ItemClickListener) {

            this.itemClickListener = itemClickListener

        }

        init {
            itemView.setOnLongClickListener(this)
            itemView.setOnClickListener(this)
        }


        override fun onClick(v: View) {

            itemClickListener.onClick(v, adapterPosition, false)
            v.startAnimation(AnimationUtils.loadAnimation(v.context, R.anim.tap))

        }

        override fun onLongClick(v: View): Boolean {

            //itemClickListener.onClick(v, adapterPosition, true)
            //v.startAnimation(AnimationUtils.loadAnimation(v.context, R.anim.tap))
            return true

        }

        var newsTitle: TextView = itemView.findViewById(R.id.item_title)
        var newsThumb: ImageView = itemView.findViewById(R.id.thumb_image)
        var saveNews: ImageView = itemView.findViewById(R.id.save_icon)

    }
}

Это мой код подачи:

package com.hfad.cointask.fragments


import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ProgressBar
import android.widget.Toast
import com.google.gson.GsonBuilder
import com.hfad.cointask.FeedActivity

import com.hfad.cointask.R
import com.hfad.cointask.adapter.CoinAdapter
import com.hfad.cointask.model.News
import com.hfad.cointask.service.CoinClient
import io.reactivex.Flowable
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import io.reactivex.processors.PublishProcessor
import io.reactivex.schedulers.Schedulers
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory

// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"

/**
 * A simple [Fragment] subclass.
 *
 */
class FeedFragment : androidx.fragment.app.Fragment() {

    private var news = mutableListOf<News>()
    private val gson = GsonBuilder().setDateFormat("yyyy-mm-dd HH:mm:ss.SSSSSS").create()
    private lateinit var newsRecyclerView: androidx.recyclerview.widget.RecyclerView
    private lateinit var newsAdapter: CoinAdapter
    private lateinit var layoutManager: androidx.recyclerview.widget.LinearLayoutManager
    private val client = FeedFragment.mCoinClient().build()
    var offset = 0
    var length = 10
    private lateinit var compositeDispossable: CompositeDisposable
    private lateinit var pagination: PublishProcessor<Int>
    private val TAG = "FeedActivity"
    private var totalItemCount = 0
    private var lastVisibleItem = 0
    private var loading = false
    private val VISIBLE_TRESHOLD = 1
    private lateinit var progressBar: ProgressBar

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        // Inflate the layout for this fragment
        var view = inflater.inflate(R.layout.fragment_feed, container, false)

        progressBar = view.findViewById(R.id.progressBar)
        newsRecyclerView = view.findViewById(R.id.news_recycler_view)
        newsRecyclerView.isNestedScrollingEnabled = false
        layoutManager = androidx.recyclerview.widget.LinearLayoutManager(this.requireContext(), androidx.recyclerview.widget.LinearLayoutManager.VERTICAL, false)
        newsRecyclerView.layoutManager = layoutManager
        newsAdapter = CoinAdapter(news, this.requireContext())
        newsRecyclerView.adapter = newsAdapter
        compositeDispossable = CompositeDisposable()
        pagination = PublishProcessor.create()

        news.clear()

        headerNews()
        setUpLoadMoreListener()
        subscribeForData()

        return view
    }

    private fun setUpLoadMoreListener() {
        newsRecyclerView.addOnScrollListener(object: androidx.recyclerview.widget.RecyclerView.OnScrollListener() {

            override fun onScrolled(recyclerView: androidx.recyclerview.widget.RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy)

                totalItemCount = newsRecyclerView.layoutManager!!.itemCount
                lastVisibleItem = layoutManager.findLastVisibleItemPosition()

                if (!loading && totalItemCount <= (lastVisibleItem + VISIBLE_TRESHOLD)) {

                    offset += length
                    pagination.onNext(offset)
                    loading = true

                }

            }

        })
    }

    private fun subscribeForData() {

        var disposable: Disposable = pagination
                .onBackpressureDrop()
                .concatMap {
                    loading = true
                    progressBar.visibility = View.VISIBLE
                    getNews(offset)
                }
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe ({ t ->
                    jsonLatest(t)
                    newsAdapter.notifyDataSetChanged()
                    loading = false
                    progressBar.visibility = View.INVISIBLE
                }
                        ,{
                    Log.e(TAG, it.toString())
                })

        compositeDispossable.add(disposable)
        pagination.onNext(offset)
    }

    private fun headerNews() {
        getHeader().enqueue(object: Callback<String> {
            override fun onResponse(call: Call<String>, response: Response<String>) {
                var headNews = response.body()
                if (headNews != null) {
                    jsonHeader(headNews)
                }
                newsAdapter.notifyDataSetChanged()
            }

            override fun onFailure(call: Call<String>?, t: Throwable?) {
                val toast = Toast.makeText(FeedActivity(), t.toString(), Toast.LENGTH_SHORT)
                toast.show()
            }

        })
    }

    private fun getHeader() = client.getHead()

    private fun getNews(offset: Int): Flowable<String> {
        return client.getNews(offset, length)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
    }

    class mCoinClient {
        private val builder = Retrofit
                .Builder()
                .baseUrl("https://api.cointelegraph.com/")
                .addConverterFactory(ScalarsConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())

        private val retrofit: Retrofit by lazy {
            builder.build()
        }

        private val client: CoinClient by lazy {
            retrofit.create(CoinClient::class.java)
        }

        fun build() = client
    }

    private fun jsonLatest(jsonString: String) {

        var latestNews = jsonString.substringAfter("\"type\":\"latest\",\"data\":")
        latestNews = latestNews.substringBefore("}]}}")
        val listNews = gson.fromJson(latestNews, Array<News>::class.java).asList()

        news.addAll(listNews)
    }

    fun jsonHeader(jsonString: String) {

        var headerNews = jsonString.substringAfter("\"type\":\"header\",\"data\":")
        headerNews = headerNews.substringBefore("},{\"type\":")
        val header: News = gson.fromJson(headerNews, News::class.java)

        news.add(header)

    }

    override fun onDestroy() {
        super.onDestroy()
        compositeDispossable.dispose()
    }


}
...