In my app I want to update the Navigation Drawer with the username's nickname and email after he's logged in.
From my MainActivity
I am starting a LoginActivity
with the startActivityForResult(intent, PICK_ACCOUNT_REQUEST);
method
to get the users registered or logged in.
After the LoginActivity
returns the Intent data
result (his NAME
and EMAIL
) back to MainActivity
, the method onActivityResult()
is called and there I try to update the class' global variables NAME
and EMAIL
with the newly received data, with no success: after every registration or log the two fields never show in the navigation drawer. Here's my code:
In the beginning of the MainActivity
class I assign two variables:
String NAME = "Sign in", EMAIL = "";
These two values are inserted in my navigation drawer. After I receive the result from LoginActivity
I want to update these two fields in the onActivityResult()
method. This way:
@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 mal = data.getStringExtra("email");
this.NAME = usr;this.EMAIL=mal;
}
}
}
with no success, in fact after completion of LoginActivity
I still visualize the old values within the Navigation Drawer because I'm not able to access the 2 EditText holding Username and Password from MainActivity
. In fact the 2 EditText are managed inside RecyclerView.ViewHolder
.
How can I set an Observer or something similar to dinamically update my Navigation Drawer's RecyclerView.Adapter?
More details below
* EDIT *
Ps. My Navigation Drawer is implemented with RecyclerView, I therefore have a RecyclerView.Adapter
class and a RecyclerView.ViewHolder
class inside the adapter. In MainActivity
I have this code:
public class MainActivity extends ActionBarActivity{
ArrayList<DrawerItem> dataList;
RecyclerView mRecyclerView; // Declaring RecyclerView
RecyclerView.Adapter mAdapter; // Declaring Adapter For Recycler View
RecyclerView.LayoutManager mLayoutManager; // Declaring Layout Manager as a linear layout manager
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
private CharSequence mTitle, mDrawerTitle;
Toolbar toolbar;
String NAME, EMAIL; int AVATARresID; //TODO update Navigation Drawer fields
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* Assigning the toolbar object to the view
and setting the the Action bar to our toolbar */
toolbar = (Toolbar) findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
// enable ActionBar app icon to behave as action to toggle nav drawer
getSupportActionBar().setDisplayHomeAsUpEnabled(true); //pulsante drawer
getSupportActionBar().setHomeButtonEnabled(true); //pulsante dietro
//Initializing
mTitle = mDrawerTitle = getTitle();
AVATARresID = R.mipmap.aka;
// Add Drawer Item to dataList
dataList = new ArrayList<>();
dataList.add(new DrawerItem(NAME,EMAIL,AVATARresID));
dataList.add(new DrawerItem("Account", R.mipmap.ic_account));
dataList.add(new DrawerItem("Tuoi Tour", R.mipmap.ic_events));
dataList.add(new DrawerItem("Prenota Tour", R.mipmap.ic_action_search));
// dataList.add(new DrawerItem("My Favorites")); // adding a header to the list
dataList.add(new DrawerItem("Others")); // adding a header to the list
dataList.add(new DrawerItem("Contatti", R.mipmap.ic_about));
dataList.add(new DrawerItem("Tutorial", R.mipmap.ic_help));
mRecyclerView = (RecyclerView) findViewById(R.id.RecyclerView);
mRecyclerView.setHasFixedSize(true);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mAdapter = new MyAdapter(dataList, mSelectedPositions);
mRecyclerView.setAdapter(mAdapter);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
mDrawerToggle = new ActionBarDrawerToggle(this,mDrawerLayout,toolbar,
R.string.drawer_open, R.string.drawer_close){
@Override
public void onDrawerOpened(View drawerView) {...}
@Override
public void onDrawerClosed(View drawerView) {...}
};
// Drawer Listener set to the Drawer toggle
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerToggle.syncState();
mRecyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(this, mRecyclerView, new RecyclerItemClickListener.OnItemClickListener() {...});
}
}
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
You implement this listener in the drawer menu and set the text views in this method based on the values received.
In your onActivityResult() call this method and pass the values
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 withSharedPreferences
.The reason why the following instructions were not working:
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 theAdapter
of the change with the methodmAdapter.notifyItemChanged(0)
(similarly to how it happens with the Observer-Observable pattern). This way the Navigation Drawer is immediately updated with the newdataList
.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 theMainActivity
, 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 intoSharedPreferences
.This is the code of
onActivityResult()
updating the navigation drawer on the fly and also saving the account's information persistently intoSharedPreferences
:This is where in
MainActivity
I check if the user is logged in, and if so the account information are loaded from SharedPreferences: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'sonCreate()
is not called a second time and the execution of the class ends with the end ofonActivityResult()
.For this reason I couldn't rely only on
SharedPreferences
to update the user's information. In fact even though theSharedPreferences
do their job well by making all the needed information available everywhere in the project, when theonCreate
method isn't called a second time, there would be no way of update theRecyclerView.Adapter
with the new information and no extra code, making theSharedPreferences
to become pointless.For these reasons, updating
MainActivity
's account fields was impossible to perform without themAdapter.notifyItemChanged(0)
, which did the job on the fly.Having said that, any subsequent call to
onCreate()
method inMainActivity
would load the account information fromSharedPreferences()
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 ofTextViews
orEditTexts
for the Strings, are you calling.setText(NAME)
/.setText(EMAIL)
on them? Can't quite make this out from your question. :)