简体   繁体   中英

Saving and Restoring FirebaseUI RecyclerView scroll state

I am new to developing, much of coding in general, and am attempting to learn by building an app in Kotlin. I have some basic functions running but I am having trouble trying to get the RecyclerView to keep it's scroll position when returning from other activities. I have searched and attempted different methods but, probably due to my lack of experience, I cannot get them to work. I have one method that looks promising but I don't know how or where to place the supplied code.

The method I'm attempting to apply

class MainActivity : AppCompatActivity() {
    private val db = FirebaseFirestore.getInstance()
    private val notebookRef = db.collection("Notebook")
    private lateinit var adapter: NoteAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val buttonAddNote =
            findViewById<FloatingActionButton>(R.id.button_add_note)
        buttonAddNote.setOnClickListener {
            startActivity(
                Intent(
                    this@MainActivity,
                    NewNoteActivity::class.java
                )
            )
        }
        setUpRecyclerView()
    }

    private fun setUpRecyclerView() {
        val query: Query = notebookRef.orderBy("priority", Query.Direction.DESCENDING)
        val options = FirestoreRecyclerOptions.Builder<Note>()
            .setQuery(query, Note::class.java)
            .build()
        adapter = NoteAdapter(options)
        val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
        recyclerView.setHasFixedSize(true)
        recyclerView.layoutManager = LinearLayoutManager(this)
        recyclerView.adapter = adapter
    }

    override fun onStart() {
        super.onStart()
        adapter.startListening()
    }

    override fun onStop() {
        super.onStop()
        adapter.stopListening()
    }
}
class Note {
    var title: String? = null
        private set
    var priority = 0
        private set

    constructor() { //empty constructor needed
    }

    constructor(title: String?, priority: Int) {
        this.title = title
        this.priority = priority
    }
}
class NoteAdapter(options: FirestoreRecyclerOptions<Note>) :
    FirestoreRecyclerAdapter<Note, NoteAdapter.NoteHolder>(options) {

    override fun onBindViewHolder(
        holder: NoteHolder,
        position: Int,
        model: Note
    ) {
        holder.textViewTitle.text = model.title
        holder.textViewPriority.text = model.priority.toString()
    }

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): NoteHolder {
        val v: View = LayoutInflater.from(parent.context).inflate(
            R.layout.note_item,
            parent, false
        )
        return NoteHolder(v)
    }

    inner class NoteHolder(itemView: View) :
        ViewHolder(itemView) {
        var textViewTitle: TextView = itemView.findViewById(R.id.text_view_title)
        var textViewPriority: TextView = itemView.findViewById(R.id.text_view_priority)
    }
}

Also the RecyclerView appears to reload after returning from an activity, which I'm hoping the above method will also fix. I've tried "singleTop" but that doesn't seem to work.

AndroidManifest.xml:

    <activity
            android:name=".MainActivity"
            android:launchMode="singleTop">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".NewNoteActivity"
            android:parentActivityName=".MainActivity" />

Help on any code cleanup is also greatly appreciated.

I do not read your huge code implementation, but I can say some important things about RecyclerView.

The RecyclerView is composed by 5 actors:

  • RecyclerView in your layout
  • ViewHolder (Each View that you needs to be repeated)
  • Collection data
  • LayoutManager (3 popular implementations: Linear - Grid - Staggered)
  • Adapter (Set each single data from collection with each viewHolder)

You only must initialize 1 time: RecyclerView LayoutManager Adapter

So, in onCreate of your Activity/Fragment you init Recycler, LayoutManager and Adapter.

After this point, you only must worry about to pass update Collection to the Adapter. The reconstruction of View, last position visible, recycler operation... Is RecyclerView internal implementation, do not worry about that behavior.

How you save in a reconstruction scenario your collection data? In saveInstanceState?

If you not have this implementation, when the Activity/Fragment is reconstructed you obtain a new Collection data, this collection you passed to RecyclerView, and this guy think this is the same data or it is new? If is new data I need to show the first position, if not I need show last position visible.

So, you are saving your Collection data?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM