簡體   English   中英

在方向更改期間保存 Recycler 視圖的實例

[英]Saving the instance of Recycler view during orientation change

我有一個使用Arraylist構建的RecyclerView Arraylist由名為ListItem的用戶定義對象組成。

每個recyclerview視圖都有一個卡片視圖。 每個CardView保存每個ListItem 我已經從RecyclerView刪除了一個CardView

當我旋轉屏幕時,會創建一個新活動,從而顯示舊數據。 但我希望recyclerview只保存updated list並且應該retain scrolled position

列表項類

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

}

主活動類

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 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)
        }
    }
}

如果縱向和橫向模式的布局相同,則可以限制在清單中重新啟動活動。

將此添加到清單中的活動中。

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

如果您不想限制屏幕方向更改,則可以使用OnSaveInstanceState方法在方向更改時保存舊數據。 您通過此方法保存的任何數據都將在您的OnCreate方法中接收到bundle 這是幫助鏈接 所以在這里,當您擁有自己的類類型的ArrayList ,您還需要使用SerializableParcelable將您的 ArrayList 放入您的 Bundle 中。

除了這些將ArrayList設為public static始終是一個解決方案,但它在面向對象的 paratime 中不是一個好的解決方案。 在內存不足的情況下,它還可以為您提供NullPointerException或數據丟失。

看起來像 initializeData 被調用了兩次,因為 onCreate 在方向改變時再次被調用,你可以使用一些布爾值來檢查數據是否已經被初始化然后跳過初始化

您正在做的是刪除傳遞給 recyclerview 的值,但是當方向更改時,recyclerview 從活動重新加載,並且活動中的原始數據再次傳遞,並且沒有任何變化,因此如果您想保存更改recyclerview 您必須更改活動中的原始數據,以便視圖重新加載時數據是相同的。

我認為您在 oncreate 方法中初始化適配器,其中將重新創建整個適配器,並且在配置更改時也會新創建所有數據。 因為你在 oncreate 方法中初始化數據。 嘗試全局維護列表,並在您在適配器中刪除時也刪除活動中列表中的項目。 或者嘗試類似視圖模型架構的東西

在項目中使用MVVM模式。 它將管理方向狀態。

MVVM RecyclerView 示例: https : //medium.com/@Varnit/android-data-binding-with-recycler-views-and-mvvm-a-clean-coding-approach-c5eaf3cf3d72

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM