其他分享
首页 > 其他分享> > android – 如何在onActivityResult方法收到Intent结果后设置Observer以更新导航抽屉

android – 如何在onActivityResult方法收到Intent结果后设置Observer以更新导航抽屉

作者:互联网

在我的应用程序中,我想在用户登录后用用户名的昵称和电子邮件更新导航抽屉.

在我的MainActivity中,我使用startActivityForResult(intent,PICK_ACCOUNT_REQUEST)启动LoginActivity;方法
让用户注册或登录.

在LoginActivity将Intent数据结果(他的NAME和EMAIL)返回给MainActivity之后,调用onActivityResult()方法,并尝试使用新接收的数据更新类的全局变量NAME和EMAIL,但没有成功:每次注册或记录两个字段都不会在导航抽屉中显示.这是我的代码:

在MainActivity类的开头,我分配了两个变量:

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或类似的东西以dinamically更新我的Navigation Drawer的RecyclerView.Adapter?

更多细节如下

*编辑*

PS.我的导航抽屉是用RecyclerView实现的,因此我在适配器内部有一个RecyclerView.Adapter类和一个RecyclerView.ViewHolder类.在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() {...});

    }
}

解决方法:

我已经解决了!

我的解决方案有两个:我在用户登录后动态更新dataList dataStructure,然后使用SharedPreferences使此更新持久化.

以下说明不起作用的原因:

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

是因为RecyclerView.Adapter mAdapter(持有我的数据的对象)没有任何方法知道发生了某些变化,因此它没有更新其数据.

为了知道实际发生了某种变化,首先我必须修改ArrayList< DrawerItems> dataList,其次我必须使用方法mAdapter.notifyItemChanged(0)通知适配器更改(类似于Observer-Observable模式的情况).这样,导航抽屉立即使用新的dataList进行更新.

这不是全部.动态更新dataList是一个易变的解决方案,因为每次用户更改活动然后返回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()不再被调用,并且类的执行以onActivityResult()的结尾.

因此,我不能仅依赖SharedPreferences来更新用户的信息.实际上即使SharedPreferences通过在项目中的所有位置提供所有需要的信息来完成他们的工作,当第二次不调用onCreate方法时,也无法使用新信息更新RecyclerView.Adapter.没有额外的代码,使SharedPreferences变得毫无意义.

出于这些原因,如果没有mAdapter.notifyItemChanged(0),即可快速完成工作,则无法更新MainActivity的帐户字段.

话虽如此,在MainActivity中对onCreate()方法的任何后续调用都会从SharedPreferences()加载帐户信息,直到用户不会在其他地方注销.

标签:android,android-studio,navigation-drawer,android-recyclerview,observer-pattern
来源: https://codeday.me/bug/20190609/1205145.html