繁体   English   中英

Android:活动和片段之间的通信

[英]Android: Communication between an Activity and a Fragment

我是新手,尝试边做边学,目前Google的搜索结果对我来说太复杂了。

我有一个活动,并成功地通过按按钮使片段打开和关闭。

public void pressedButton(View v) {
    FragmentActivity fragmentActivity = new FragmentActivity();

    FragmentManager fragmentManager = getSupportFragmentManager();
    android.support.v4.app.FragmentTransaction ft = fragmentManager.beginTransaction();

    ft.add(R.id.frame_which_takes_the_fragment, FragmentActivity, "FRAGMENT_TAG");
    ft.commit();

按照片段类的规定,我在Activity中实现了其“ OnFragmentInteractionListener”接口,并覆盖了onFragmentInteraction方法。

@Override
public void onFragmentInteraction(Uri uri) {

}

现在我不知道该如何进步。 如何从活动向片段发送变量(例如,更新用户界面中的数字),以及如何向后发送信息?

请记住我是一个流血的初学者,并尝试使其尽可能简单和基本。

提前致谢。

那么,您已经在片段中创建了一个接口并在活动中实现了它? 然后,您只需要根据需要创建界面。 onFragmentInteraction(Uri uri)方法只是一个示例,如果您不想将Uri从片段传递到活动,则可以删除该示例。

因此,要传递数字,您的界面应如下所示:

interface Listener {
    void onNumberChanged(int number);
}

相关的片段代码:

listener.onNumberChanged(someNumber);

相关活动代码:

@Override
public void onNumberChanged(int number) {
    someTextView.setText(Integer.toString(number));
}

随着ViewModel的发布,您可以使用shared ViewModel在片段和活动之间进行通信。 您只需要在activity范围内创建ViewModel ,该ViewModel将与activity和所有子fragment共享。

SharedViewModel sharedViewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel::class.java);

然后观察数据

sharedViewModel.inputNumber.observe(this, observer);  // observer is your observer object

如何从活动向片段发送变量(例如,在用户界面中更新数字)?

我试图通过从适配器获取ListFragment并调用fragment方法来做到这一点,但是却出现了以下错误:

IllegalStateException:无法从分离的片段访问ViewModels

我的解决方案是改用LocalBroadcastManager:

活动代码

LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);
Intent broadcastIntent = new Intent("MAP_SETTINGS_CHANGED");
broadcastIntent.putExtra("NUMBER_TO_SHOW_IN_FRAGMENT", 11);
localBroadcastManager.sendBroadcast(broadcastIntent);

ListFragment /片段代码

private Context mContext;
private BroadcastReceiver mBroadcastReceiver;

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    mContext = context;

    mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(final Context context, Intent intent) {

            String action = intent.getAction();
            if ("MAP_SETTINGS_CHANGED".equals(action)) {
                int numberToShow = intent.getIntExtra("NUMBER_TO_SHOW_IN_FRAGMENT", -1);
                showNumber(numberToShow);
            }
        }
    };

    LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(mContext);
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction("MAP_SETTINGS_CHANGED");
    localBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);

}

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

    LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(mContext);
    localBroadcastManager.unregisterReceiver(mBroadcastReceiver);

    mContext = null;
}

同一活动的两个片段之间有多种通信方式。

  1. 最简单的方法是使用静态关键字。 在这里,我们可以将要与其他片段共享的方法和变量定义为静态,并且其他片段可以直接访问这些变量。 但是这种方法的最大问题是它会导致内存泄漏(静态定义的COZ)。
  2. 另一种方法是使用Interfaces 在这里,我们在一个片段中使用接口的方法来传递值,然后在父活动中实现此接口,并在那里覆盖该方法,然后使用该方法将值传递给子片段。
  3. 另一种最有效的方法是使用ViewModel 我们知道ViewModel会保留到创建它的整个范围为止。 因此,通常我们使用关键字将ViewModel绑定到视图,就像mainViewModel = ViewModelProviders.of(this).get(MainViewModel.class); 因此,如果我们使用关键字,则ViewModel的作用域将一直保留到仅破坏片段为止,一旦破坏了片段,也将清除ViewModel。 因此,如果我们将getActivity()用作ViewModel的范围,则ViewModel将保留到Activity被销毁为止。 现在假设您有一个用于A片段的ViewModelA ,并且想要将一些值从A传递到B片段,现在您可以做的是,可以将B片段绑定到ViewModelBViewModelA ,因此可以观察到片段BViewModelA的某些值的变化。

ViewModels方法

片段可以使用其活动范围共享ViewModel 来处理此通信 ,如以下示例代码所示:在Google的官方文档中对此进行了明确说明。 https://developer.android.com/topic/libraries/architecture/viewmodel#sharing

public class SharedViewModel extends ViewModel {
    private final MutableLiveData<Item> selected = new MutableLiveData<Item>();

    public void select(Item item) {
        selected.setValue(item);
    }

    public LiveData<Item> getSelected() {
        return selected;
    }
}


public class MasterFragment extends Fragment {
    private SharedViewModel model;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        itemSelector.setOnClickListener(item -> {
            model.select(item);
        });
    }
}

public class DetailFragment extends Fragment {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        model.getSelected().observe(this, { item ->
           // Update the UI.
        });
    }
}
enter code here

另一个研究此问题的非常好的博客:Android应用程序中Fragment和Activity之间进行通信的8种方法。 https://hackernoon.com/8-ways-to-communicate-between-fragment-and-activity-in-android-apps-235b60005d04

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM