2

I have a RecyclerView which was build using an Arraylist. That Arraylist consists of User defined objects named ListItem.

Each recyclerview has a card view. Each CardView holds each ListItem. I have removed one CardView from that RecyclerView.

When I rotate the screen , A new Activity is created which results in showing the old data. But I want the recyclerview to hold only updated list and should retain the 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)
        }
    }
}
Shaheen Ahamed S
  • 176
  • 2
  • 11

5 Answers5

2

You can restrict activity restarting in your Manifest if you have same layout for Portrait and Landscape mode.

Add this to your activity in the manifest.

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

If you don't want to restrict screen orientation changes, then you can use OnSaveInstanceState method to save your older data when orientation changed. Whatever data you save via this method you will receive it in your OnCreate Method in bundle. Here is the helping link. So here as you have ArrayList of your own class type you also need to use Serializable or Parcelable to put your ArrayList in your Bundle.

Except these making ArrayList as public static is always a solution, But its not a good solution in Object Oriented paratime. It can also give you NullPointerException or loss of data, in case of low memory conditions.

Asad Ali Choudhry
  • 4,985
  • 4
  • 31
  • 36
  • I have Different UI design for portrait and landscape . While using this, when I change the screen from landscape to potrait , the same UI design which is in landscape is applied for portrait also . – Shaheen Ahamed S Jul 02 '19 at 07:33
  • if it helps, please accept my answer. or let me know if you need further assistance. – Asad Ali Choudhry Jul 03 '19 at 08:31
0

It looks like initializeData is called twice since onCreate is called again on orientation change, you could use some boolean to check if data has been already initialized then skip initializing

Alexey
  • 7,127
  • 9
  • 57
  • 94
0

What you are doing is you are deleting the values that are passed down to the recyclerview but when the orientation changes the recyclerview reloads from activity and the original data from activity is passed down again and nothing changes, so if you want to save the changes in recyclerview you have to change the original data in the activity so that if the view reloads the data is the same.

raj kavadia
  • 926
  • 1
  • 10
  • 30
0

I think u initialize adapter in oncreate method in which the whole adapter will be recreated and all datas is also newly created when configuration changes. Because u init data in oncreate method. Try something globally maintain the list and also delete the item in the list in activity when u delete in adapter also. Or try something like view model architecture

Karthick Ramanathan
  • 642
  • 3
  • 9
  • 20
0

Use MVVM pattern in the project. It will manage the orientation state.

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

Afinas EM
  • 2,755
  • 1
  • 15
  • 28