如何在 onActivityResult 方法收到 Intent 结果后设置 Observer 以更新导航抽屉
How to set an Observer to Update Navigation Drawer after onActivityResult method's received an Intent result
在我的应用程序中,我想在他登录后使用用户名的昵称和电子邮件更新导航抽屉。
从我的 MainActivity
我开始 LoginActivity
使用 startActivityForResult(intent, PICK_ACCOUNT_REQUEST);
方法
让用户注册或登录。
LoginActivity
returnsIntent data
结果(他的NAME
和EMAIL
)返回MainActivity
后,方法onActivityResult()
被调用,我尝试用新收到的数据更新 class' 全局变量 NAME
和 EMAIL
,但没有成功:每次注册或登录后,这两个字段从不显示在导航抽屉中。这是我的代码:
在MainActivity
开头class我赋值了两个变量:
String NAME = "Sign in", EMAIL = "";
这两个值已插入我的导航抽屉中。从 LoginActivity
收到结果后,我想在 onActivityResult()
方法中更新这两个字段。这样:
@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;
}
}
}
没有成功,实际上在 LoginActivity
完成后,我仍然在导航抽屉中看到旧值,因为我无法从 MainActivity
访问包含用户名和密码的 2 个 EditText .实际上 2 个 EditText 是在 RecyclerView.ViewHolder
中管理的。
如何设置 Observer 或类似的东西来动态更新我的导航抽屉的 RecyclerView.Adapter?
下面有更多详细信息
* 编辑 *
Ps。我的导航抽屉是用 RecyclerView 实现的,因此我在适配器中有一个 RecyclerView.Adapter
class 和一个 RecyclerView.ViewHolder
class。在 MainActivity
我有这个代码:
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() {...});
}
}
我无法发表评论,所以发帖作为回答 - 您正在更新变量,但您是在更新 DrawerLayout
的视图本身吗?我假设您有某种 TextViews
或 EditTexts
用于字符串,您是在调用它们 .setText(NAME)
/.setText(EMAIL)
吗?不能完全从你的问题中看出这一点。 :)
在您的导航抽屉中,我相信您正在使用文本视图来显示姓名和电子邮件。您需要在侦听器的帮助下传递这些值,然后在抽屉文本视图中设置这些文本。
创建一个监听器,它有一个接受姓名和电子邮件的方法
public interface ChangeListener {
void displayNameAndEmail(String name, String email );
}
您在抽屉菜单中实现此侦听器,并根据收到的值在此方法中设置文本视图。
@Override
private void displayNameAndEmail(String name, String email ) {
mEmailTextView.setText(email);
mNameTextView.setText(name);
};
在您的 onActivityResult() 中调用此方法并传递值
ChangeListener.displayNameAndEmail(name, email );
我已经解决了!
我的解决方案是双重的:我在用户登录后即时更新 dataList
数据结构,然后使用 SharedPreferences
.
使此更新持久化
以下说明不起作用的原因:
String usr = data.getStringExtra("username");
String mal = data.getStringExtra("email");
this.NAME = usr; this.EMAIL=mal;
是因为RecyclerView.Adapter mAdapter
(保存我的数据的对象)没有任何方法知道发生了某种变化,因此它没有更新它的数据。
为了让它知道某个变化确实发生了,首先我必须修改 ArrayList<DrawerItems> dataList
,然后我必须用方法 Adapter
通知变化 Adapter
=18=](类似于 Observer-Observable 模式)。这样导航抽屉会立即更新为新的 dataList
。
这还不是全部。简单地即时更新 dataList
是一个不稳定的解决方案,因为每次用户更改 activity 然后返回到 MainActivity
,NavigationDrawer 都会用旧数据再次初始化(丢失过去状态期间获取的任何信息,因此加载空的 NAME 和 EMAIL 变量)。因此,为了使帐户信息持久化,有必要将它们保存到 SharedPreferences
中。
这是 onActivityResult()
动态更新导航抽屉并将帐户信息永久保存到 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);
}
}
}
这是 MainActivity
我检查用户是否登录的地方,如果是,则从 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);
//... ...
}
另一方面,为了解决我的问题,我不得不注意到(经过大量调试)方法 onActivityResult()
完成后,MainActivity 的 onCreate()
不会被第二次调用时间和 class 的执行在 onActivityResult()
.
结束时结束
因此,我不能仅依靠 SharedPreferences
来更新用户信息。事实上,即使 SharedPreferences
通过使所有需要的信息在项目的任何地方都可用来很好地完成他们的工作,当 onCreate
方法没有被第二次调用时,将无法更新RecyclerView.Adapter
包含新信息且没有额外代码,使 SharedPreferences
变得毫无意义。
由于这些原因,如果没有 mAdapter.notifyItemChanged(0)
更新 MainActivity
的帐户字段是不可能的,它可以即时完成工作。
话虽如此,在 MainActivity
中对 onCreate()
方法的任何后续调用都会从 SharedPreferences()
加载帐户信息,直到用户不会在其他地方注销。
在我的应用程序中,我想在他登录后使用用户名的昵称和电子邮件更新导航抽屉。
从我的 MainActivity
我开始 LoginActivity
使用 startActivityForResult(intent, PICK_ACCOUNT_REQUEST);
方法
让用户注册或登录。
LoginActivity
returnsIntent data
结果(他的NAME
和EMAIL
)返回MainActivity
后,方法onActivityResult()
被调用,我尝试用新收到的数据更新 class' 全局变量 NAME
和 EMAIL
,但没有成功:每次注册或登录后,这两个字段从不显示在导航抽屉中。这是我的代码:
在MainActivity
开头class我赋值了两个变量:
String NAME = "Sign in", EMAIL = "";
这两个值已插入我的导航抽屉中。从 LoginActivity
收到结果后,我想在 onActivityResult()
方法中更新这两个字段。这样:
@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;
}
}
}
没有成功,实际上在 LoginActivity
完成后,我仍然在导航抽屉中看到旧值,因为我无法从 MainActivity
访问包含用户名和密码的 2 个 EditText .实际上 2 个 EditText 是在 RecyclerView.ViewHolder
中管理的。
如何设置 Observer 或类似的东西来动态更新我的导航抽屉的 RecyclerView.Adapter?
下面有更多详细信息
* 编辑 *
Ps。我的导航抽屉是用 RecyclerView 实现的,因此我在适配器中有一个 RecyclerView.Adapter
class 和一个 RecyclerView.ViewHolder
class。在 MainActivity
我有这个代码:
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() {...});
}
}
我无法发表评论,所以发帖作为回答 - 您正在更新变量,但您是在更新 DrawerLayout
的视图本身吗?我假设您有某种 TextViews
或 EditTexts
用于字符串,您是在调用它们 .setText(NAME)
/.setText(EMAIL)
吗?不能完全从你的问题中看出这一点。 :)
在您的导航抽屉中,我相信您正在使用文本视图来显示姓名和电子邮件。您需要在侦听器的帮助下传递这些值,然后在抽屉文本视图中设置这些文本。
创建一个监听器,它有一个接受姓名和电子邮件的方法
public interface ChangeListener {
void displayNameAndEmail(String name, String email );
}
您在抽屉菜单中实现此侦听器,并根据收到的值在此方法中设置文本视图。
@Override
private void displayNameAndEmail(String name, String email ) {
mEmailTextView.setText(email);
mNameTextView.setText(name);
};
在您的 onActivityResult() 中调用此方法并传递值
ChangeListener.displayNameAndEmail(name, email );
我已经解决了!
我的解决方案是双重的:我在用户登录后即时更新 dataList
数据结构,然后使用 SharedPreferences
.
以下说明不起作用的原因:
String usr = data.getStringExtra("username");
String mal = data.getStringExtra("email");
this.NAME = usr; this.EMAIL=mal;
是因为RecyclerView.Adapter mAdapter
(保存我的数据的对象)没有任何方法知道发生了某种变化,因此它没有更新它的数据。
为了让它知道某个变化确实发生了,首先我必须修改 ArrayList<DrawerItems> dataList
,然后我必须用方法 Adapter
通知变化 Adapter
=18=](类似于 Observer-Observable 模式)。这样导航抽屉会立即更新为新的 dataList
。
这还不是全部。简单地即时更新 dataList
是一个不稳定的解决方案,因为每次用户更改 activity 然后返回到 MainActivity
,NavigationDrawer 都会用旧数据再次初始化(丢失过去状态期间获取的任何信息,因此加载空的 NAME 和 EMAIL 变量)。因此,为了使帐户信息持久化,有必要将它们保存到 SharedPreferences
中。
这是 onActivityResult()
动态更新导航抽屉并将帐户信息永久保存到 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);
}
}
}
这是 MainActivity
我检查用户是否登录的地方,如果是,则从 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);
//... ...
}
另一方面,为了解决我的问题,我不得不注意到(经过大量调试)方法 onActivityResult()
完成后,MainActivity 的 onCreate()
不会被第二次调用时间和 class 的执行在 onActivityResult()
.
因此,我不能仅依靠 SharedPreferences
来更新用户信息。事实上,即使 SharedPreferences
通过使所有需要的信息在项目的任何地方都可用来很好地完成他们的工作,当 onCreate
方法没有被第二次调用时,将无法更新RecyclerView.Adapter
包含新信息且没有额外代码,使 SharedPreferences
变得毫无意义。
由于这些原因,如果没有 mAdapter.notifyItemChanged(0)
更新 MainActivity
的帐户字段是不可能的,它可以即时完成工作。
话虽如此,在 MainActivity
中对 onCreate()
方法的任何后续调用都会从 SharedPreferences()
加载帐户信息,直到用户不会在其他地方注销。