Сохранение экземпляра вида Recycler во время изменения ориентации - PullRequest
1 голос
/ 02 июля 2019

У меня есть RecyclerView, который был собран с использованием Arraylist.Что Arraylist состоит из определенных пользователем объектов с именем ListItem.

Каждый recyclerview имеет вид карты.Каждый CardView содержит каждый ListItem.Я удалил один CardView из этого RecyclerView.

Когда я поворачиваю экран, создается новое действие, в результате которого отображаются старые данные.Но я хочу, чтобы recyclerview содержал только updated list и должен retain scrolled position.

ListItem class :

class ListItem(var title: String, var info: String,  val imageResource: Int) { 

}

MainActivity class :

class MainActivity : AppCompatActivity() {
    private lateinit var mSportsData: ArrayList<ListItem>
    private lateinit var mAdapter: MyAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val gridColumnCount = resources.getInteger(R.integer.grid_column_count)
        recycler_view.layoutManager = GridLayoutManager(this,gridColumnCount)
        mSportsData = ArrayList()
        recycler_view.setHasFixedSize(true)
        initializeData()
        recycler_view.adapter = mAdapter

        var swipeDirs = 0
        if (gridColumnCount <= 1) {
            swipeDirs = ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
        }

        val helper = ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT or ItemTouchHelper.UP or ItemTouchHelper.DOWN,swipeDirs) {
            override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
                val from = viewHolder.adapterPosition
                val to = target.adapterPosition
                Collections.swap(mSportsData,from,to)
                mAdapter.notifyItemMoved(from,to)
                return true
            }
            override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
                mSportsData.removeAt(viewHolder.adapterPosition)
                mAdapter.notifyItemRemoved(viewHolder.adapterPosition)
            }
        })
        helper.attachToRecyclerView(recycler_view)
    }

    private fun initializeData() {
        val sportsList : Array<String> = resources.getStringArray(R.array.sports_titles)
        Log.d("Printing","$sportsList")
        val sportsInfo : Array<String> = resources.getStringArray(R.array.sports_info)
        val sportsImageResources : TypedArray = resources.obtainTypedArray(R.array.sports_images)

        mSportsData.clear()

        for (i in sportsList.indices-1) {
            Log.d("Printing","${sportsList[i]},${sportsInfo[i]},${sportsImageResources.getResourceId(i,0)}")
            mSportsData.add(ListItem(sportsList[i], sportsInfo[i], sportsImageResources.getResourceId(i, 0)))
        }
        sportsImageResources.recycle()
        mAdapter = MyAdapter(mSportsData,this)
        mAdapter.notifyDataSetChanged()
    }

    fun resetSports(view: View) {
        initializeData()
    }
}

MyAdapter class :

class MyAdapter(var mSportsData: ArrayList<ListItem>, var context: Context) : RecyclerView.Adapter<MyAdapter.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(LayoutInflater.from(context).inflate(R.layout.wordlist_item,parent,false))
    }

    override fun getItemCount() = mSportsData.size

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val listItem = mSportsData.get(position)
        holder.bindTo(listItem)
    }

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
        init {
            itemView.setOnClickListener(this)
        }
        override fun onClick(view: View) {
            val currentSport = mSportsData.get(adapterPosition)
            val detailIntent = Intent(context, DetailActivity::class.java)
            detailIntent.putExtra("title", currentSport.title)
            detailIntent.putExtra("image_resource", currentSport.imageResource)
            context.startActivity(detailIntent)
        }
        fun bindTo(currentSport : ListItem){
            itemView.heading_textview.setText(currentSport.title)
            itemView.description_textview.setText(currentSport.info)
            Glide.with(context).load(currentSport.imageResource).into(itemView.image_view)
        }
    }
}

Ответы [ 5 ]

0 голосов
/ 02 июля 2019

Использовать шаблон MVVM в проекте.Он будет управлять состоянием ориентации.

MVVM RecyclerView пример: https://medium.com/@Varnit/android-data-binding-with-recycler-views-and-mvvm-a-clean-coding-approach-c5eaf3cf3d72

0 голосов
/ 02 июля 2019

Я думаю, что вы инициализируете адаптер в методе oncreate, в котором весь адаптер будет воссоздан, и все данные также создаются заново при изменении конфигурации. Потому что вы инициализируете данные в методе oncreate. Попробуйте что-то глобально сохранить список, а также удалить элемент в списке в действии, когда вы также удалите в адаптере. Или попробуйте что-то вроде представления модели архитектуры

0 голосов
/ 02 июля 2019

То, что вы делаете, это то, что вы удаляете значения, которые передаются в просмотр повторного использования, но при изменении ориентации просмотр повторного загрузки перезапускается из действия, и исходные данные из действия снова передаются, и ничего не меняется, поэтому, если вы хотите сохранитьИзменения в представлении реселлера: необходимо изменить исходные данные в операции, чтобы при повторной загрузке представления данные были такими же.

0 голосов
/ 02 июля 2019

Вы можете ограничить перезапуск активности в манифесте, если у вас одинаковый макет для портретного и альбомного режимов.

Добавьте это к своей активности в манифесте.

 <activity android:name=".activity.YourActivity"
    android:label="@string/app_name"
    android:configChanges="orientation|screenSize"/>

Если вы неЕсли вы не хотите ограничивать изменения ориентации экрана, вы можете использовать метод OnSaveInstanceState, чтобы сохранить старые данные при изменении ориентации.Какие бы данные вы ни сохранили этим методом, вы получите их по вашему OnCreate методу в bundle.Вот справочная ссылка .Итак, здесь у вас есть ArrayList вашего собственного типа класса, вам также нужно использовать Serializable или Parcelable , чтобы поместить ваш ArrayList в ваш Bundle.

За исключением того, что ArrayList в качестве public static всегда является решением, но это не очень хорошее решение в объектно-ориентированном времени.Он также может дать вам NullPointerException или потерю данных в случае нехватки памяти.

0 голосов
/ 02 июля 2019

Похоже, initializeData вызывается дважды, так как onCreate вызывается снова при изменении ориентации, вы можете использовать некоторое логическое значение, чтобы проверить, были ли данные уже инициализированы, затем пропустить инициализацию

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...