如何将MasterActivity中的Argument传递给DetailActivity的NavigationDrawerFragment?

时间:2015-06-25 06:05:17

标签: android android-fragments navigation-drawer master-detail

TL; DR VERSION:

在Android主 - 详细信息模式中,如何让MasterActivity将值传递给DetailFragment的父活动(DetailActivity)?因为DetailActivity是存储NavigationDrawerFragment的文件。

我考虑过的事情:

  • 回调(我不知道这是怎么回事)
  • 使用getActivity()并在父活动上调用函数来传递参数。它似乎不那么干净"解决方案和高度耦合。

有更好的方法吗?

LONG VERSION

我有一个主 - 细节模式,但细节已经改变,以便" up"按钮不再返回主列表,而是打开导航抽屉。

现在,我有"假"代码,所以我的导航抽屉有3个项目,当你第一次点击主列表中的项目时,它们都打开了相同的页面。

我的主要问题是:主列表可以将SongDetailFragment.ARG_ITEM_ID参数传递给详细信息,但导航抽屉无法访问SongDetailFragment.java中的SongDetailFragment.ARG_ITEM_ID参数,因为导航抽屉在SongDetailActivity.java中实现。

主列表使用行detailIntent.putExtra(SongDetailFragment.ARG_ITEM_ID, id);将参数传递给详细信息片段

SongListActivity.java

/**
 * Callback method from {@link SongListFragment.Callbacks}
 * indicating that the item with the given ID was selected.
 */
@Override
public void onItemSelected(String id) {
    if (mTwoPane) {
        // In two-pane mode, show the detail view in this activity by
        // adding or replacing the detail fragment using a
        // fragment transaction.
        Bundle arguments = new Bundle();
        arguments.putString(SongDetailFragment.ARG_ITEM_ID, id);
        SongDetailFragment fragment = new SongDetailFragment();
        fragment.setArguments(arguments);
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.songlist_detail_container, fragment)
                .commit();

    } else {
        // In single-pane mode, simply start the detail activity
        // for the selected item ID.
        Intent detailIntent = new Intent(this, SongDetailActivity.class);
        detailIntent.putExtra(SongDetailFragment.ARG_ITEM_ID, id); //<-------- Argument
        startActivity(detailIntent);
    }
}

但是当我点击导航抽屉中的3个虚拟选项之一时,我无法传递该参数,因为导航抽屉位于SongDetailActivity.java中。

SongDetailActivity.java

//---------- NAVIGATION DRAWER -------------
    @Override
    public void onNavigationDrawerItemSelected(int position) {
        // update the main content by replacing fragments
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction()
                .replace(R.id.songlist_detail_container, PlaceholderFragment.newInstance(position + 1))
                .commit();
    }

我尝试将此代码从SongDetailFragment.java的onCreate方法复制并粘贴到SongDetailActivity.java的onCreate方法中,希望我能从SongDetailActivity访问相同的SongDetailFragment.ARG_ITEM_ID变量,但它有编译错误,如Cannot resolve getArguments()。我后来意识到,师父只是&#34;额外的&#34;在片段中,而不是活动。

SongDetailFragment.java

 @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
        if (getArguments().containsKey(ARG_ITEM_ID)) {
            // Load the dummy title specified by the fragment
            // arguments. In a real-world scenario, use a Loader
            // to load title from a title provider.
            mItem = SongItem.ITEM_MAP.get(getArguments().getString(ARG_ITEM_ID));
        }
    }

所以,我需要某种方法让导航抽屉存储来自Master的SongDetailFragment.ARG_ITEM_ID变量,这样它就可以从模型中为每个视图获取正确的数据。如何我能这样做吗?

共享偏好设置?我考虑过使用共享首选项,但我认为这是一个糟糕的主意,因为很难删除所有离开&#34;细节&#34 ;.我想我需要一些不那么全球化的东西。最好是,如果我可以让Master将参数传递给SongDetailActivity(最终传递给导航抽屉),那将是完美的!

回调?我正在查看我的代码文件,想到了什么,我发现了这个&#34;回调&#34;使用Android Studio的Master-Detail向导生成的内容。当它说&#34时,它听起来很合适;这个机制允许活动被通知项目选择,&#34;但我不确定。欢迎任何有关回调适用性的见解或反馈!

    /**
     * A callback interface that all activities containing this fragment must
     * implement. This mechanism allows activities to be notified of item
     * selections.
     */
    public interface Callbacks {
        /**
         * Callback for when an item has been selected.
         */
        public void onItemSelected(String id);
    }

    /**
     * A dummy implementation of the {@link Callbacks} interface that does
     * nothing. Used only when this fragment is not attached to an activity.
     */
    private static Callbacks sDummyCallbacks = new Callbacks() {
        @Override
        public void onItemSelected(String id) {

        }
    };

 @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        // Activities containing this fragment must implement its callbacks.
        if (!(activity instanceof Callbacks)) {
            throw new IllegalStateException("Activity must implement fragment's callbacks.");
        }

        mCallbacks = (Callbacks) activity;
    }

    @Override
    public void onDetach() {
        super.onDetach();

        // Reset the active callbacks interface to the dummy implementation.
        mCallbacks = sDummyCallbacks;
    }

    @Override
    public void onListItemClick(ListView listView, View view, int position, long id) {
        super.onListItemClick(listView, view, position, id);

        // Notify the active callbacks interface (the activity, if the
        // fragment is attached to one) that an item has been selected.
        mCallbacks.onItemSelected(SongItem.ITEMS.get(position).id);
    }

getActivity()和Setter方法?我发现了这个问题Passing data between a fragment and its container activity。我会尝试一下,但似乎强烈耦合,就像一个糟糕的解决方案。它只是使用父活动的方法(例如setter)通过片段将数据直接传递给父活动。

1 个答案:

答案 0 :(得分:0)

我错误地认为SongListActivity.java只是为SongDetailFragment.java创建了一个意图,但它正在为SongDetailActivity.java创建一个意图。当我看到SongDetailFragment.ARG_ITEM_ID时,它让我很困惑。

我误解的代码:

Intent detailIntent = new Intent(this, SongDetailActivity.class);
        detailIntent.putExtra(SongDetailFragment.ARG_ITEM_ID, id); //<-------- Argument
        startActivity(detailIntent);

我的解决方案:

我不得不改变很多方法来获得这个解决方案,我不记得我做过的所有事情,但这是最终的结果:

所以,我实际上只需要进入SongDetailActivity.java的{​​{1}}方法,然后像这样提取捆绑的参数:

onCreate

然后我必须在mSongId = getIntent().getStringExtra(SongDetailFragment.ARG_ITEM_ID); 的{​​{1}}方法中编辑它,并让它实际实例化正确的片段,然后传递包中的SongDetailActivity.java

onNavigationDrawerItemSelected

现在有效!我希望这有助于某人。

结论

要将一个参数从主文件(mSongId)传递到详细信息的导航抽屉(@Override public void onNavigationDrawerItemSelected(int position) { // update the main content by replacing fragments FragmentManager fragmentManager = getSupportFragmentManager(); //------------ THE DEFAULT CODE THAT WASN'T PASSING THE DATA TO THE FRAGMENT---------- if(position == 1) { fragmentManager.beginTransaction() .replace(R.id.songlist_detail_container, PlaceholderFragment.newInstance(position + 1, mSongId)) //<------ I actually do not want a placeholder fragment. I want my SongDetailFragment. .commit(); } // ------------THE CODE I ADDED THAT WORKS-------------: else { SongDetailFragment sdf = new SongDetailFragment(); //<--------- Correct fragment class that I actually needed. Bundle args = new Bundle(); args.putString(SongDetailFragment.ARG_ITEM_ID, mSongId); //<-------- PASS ALONG THE PARAMETER sdf.setArguments(args); fragmentManager.beginTransaction() .replace(R.id.songlist_detail_container,sdf) .commit(); } } 的{​​{1}}),我不得不将其作为额外内容从掌握细节,并修改细节的导航抽屉回调以使用参数。就像我想的那样,我不需要将片段中的任何内容传递给它的父活动。