How to set an Observer to Update Navigation Drawer after onActivityResult method's received an Intent result

依然范特西╮ 提交于 2019-12-05 18:17:00

I've solved it!

My solution is twofold: I both update the dataList dataStructure on the fly after the user's login, and then make this update persistent with SharedPreferences.

The reason why the following instructions were not working:

String usr = data.getStringExtra("username");
String mal = data.getStringExtra("email");
this.NAME = usr; this.EMAIL=mal;

was because the RecyclerView.Adapter mAdapter (the object holding my data) did not have any way to know that a certain change took place, and it therefore didn't update its data.

For it to know that a certain change had actually occurred, first of all I had to modify the ArrayList<DrawerItems> dataList, and secondly I had to notify the Adapter of the change with the method mAdapter.notifyItemChanged(0) (similarly to how it happens with the Observer-Observable pattern). This way the Navigation Drawer is immediately updated with the new dataList.

This wasn't all. Simply updating the dataList on the fly was a volatile solution, since every time the user changes activity and then goes back to the MainActivity, the NavigationDrawer is initialized again with the old data (losing any acquired information during past states, and therefore loading empty NAME and EMAIL variables). Thus, in order to make the account information persistent was necessary to save them into SharedPreferences.

This is the code of onActivityResult() updating the navigation drawer on the fly and also saving the account's information persistently into SharedPreferences:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
    // Check which request we're responding to
    if (requestCode == PICK_ACCOUNT_REQUEST) {
        // Make sure the request was successful
        if (resultCode == RESULT_OK) {
            // The user picked a contact.
            String usr = data.getStringExtra("username");
            String mail = data.getStringExtra("email");

            SharedPreferences usrData = getSharedPreferences(usr_loggedin, MODE_PRIVATE);
            SharedPreferences.Editor editor = usrData.edit();
            editor.clear();
            editor.putBoolean("usraccount",true).commit();
            editor.putString("username",usr).commit();
            editor.putString("email",mail).commit();

            dataList.remove(0);
            dataList.add(0,new DrawerItem(usr,mail,AVATARresID));
            mAdapter.notifyItemChanged(0);
        }
    }
}

This is where in MainActivity I check if the user is logged in, and if so the account information are loaded from SharedPreferences:

//...
String NAME,EMAIL; int AVATARresID;

@Override
protected void onCreate(Bundle savedInstanceState) {
    //...

    //Initializing
    SharedPreferences usrData = getSharedPreferences(usr_loggedin, MODE_PRIVATE);
    AVATARresID = R.mipmap.aka;
    // Add Drawer Item to dataList
    dataList = new ArrayList<>();
    dataList = prepareDatalist(dataList, NAME, EMAIL, AVATARresID);

    mRecyclerView = (RecyclerView) findViewById(R.id.RecyclerView);
    mRecyclerView.setHasFixedSize(true);
    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);

    mAdapter = new MyAdapter(dataList, mSelectedPositions);

    if(usrData.contains("usraccount")){
        String usr,mail;
        usr = usrData.getString("username",usr_loggedin);
        mail = usrData.getString("email",usr_loggedin);
        dataList.remove(0);
        dataList.add(0,new DrawerItem(usr,mail,AVATARresID));
        mAdapter.notifyItemChanged(0);
    }

    mRecyclerView.setAdapter(mAdapter);
    //... ...
}

As a side not, to solve my problems I had to notice (with a great deal of debugging) that after the method onActivityResult() has finished, the MainActivity's onCreate() is not called a second time and the execution of the class ends with the end of onActivityResult().

For this reason I couldn't rely only on SharedPreferences to update the user's information. In fact even though the SharedPreferences do their job well by making all the needed information available everywhere in the project, when the onCreate method isn't called a second time, there would be no way of update the RecyclerView.Adapter with the new information and no extra code, making the SharedPreferences to become pointless.

For these reasons, updating MainActivity's account fields was impossible to perform without the mAdapter.notifyItemChanged(0), which did the job on the fly.

Having said that, any subsequent call to onCreate() method in MainActivity would load the account information from SharedPreferences() until the user wouldn't logout somewhere else.

I cannot comment, so posting as an answer - you are updating the variables, but are you updating the DrawerLayout's view itself? I assume you have some kind of TextViews or EditTexts for the Strings, are you calling .setText(NAME)/.setText(EMAIL) on them? Can't quite make this out from your question. :)

In your navigation drawer I believe you are using the textviews to display the name and email. You need to pass these values with the help of a listener and then set these texts in the drawer text views.

Create a listener which has a method which takes name and email

public interface ChangeListener {
     void displayNameAndEmail(String name, String email );
}

You implement this listener in the drawer menu and set the text views in this method based on the values received.

@Override 
private void displayNameAndEmail(String name, String email ) {
      mEmailTextView.setText(email);
      mNameTextView.setText(name);
};

In your onActivityResult() call this method and pass the values

ChangeListener.displayNameAndEmail(name, email );
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!