【问题标题】:How to Synchronize Data Between Viewpager Fragments如何在 Viewpager 片段之间同步数据
【发布时间】:2019-07-16 03:38:00
【问题描述】:

通过以下代码,我可以单击一个按钮将字符串从一个片段(片段 A)发送到 MainActivity。我将如何从 MainActivity 中检索字符串并将其一次性显示在片段 B 上?我希望片段同步运行;在我单击片段 A 中的按钮后立即让片段 B 自行更新。我似乎在 SO 中找不到任何内容。

界面:

public interface OnDataListener {
    public void onDataReceived(String data);
}

Fragment A 数据监听器:

OnDataListener mOnDataListener;

@Override
public void onAttach(Context context) {
    try{
        mOnDataListener = (OnDataListener) context;
        Log.d(TAG, "onAttach was called" + context);
    }catch (ClassCastException e){
        Log.e(TAG, "onAttach: ClassCastException: " + e.getMessage() );
    }
    super.onAttach(context);
}

Fragment A 的 onCreateView 中的按钮逻辑:

button.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {

          String newTextString = editTextView.getText().toString();
          mOnDataListener.onDataReceived(newTextString);

        }
      });

MainActivity 数据接收器

public class MainActivity extends AppCompatActivity implements OnDataListener {


@Override
public void onDataReceived(String data) {

    Log.e(TAG, "MainActivity received this string " + data );

            }
}

【问题讨论】:

    标签: android android-fragments android-viewpager android-button


    【解决方案1】:

    解决方案 1:使用回调

    //如果您的片段实例处于活动状态,这将起作用,因此请检查 viewpager offscreenpage 限制

    (您也可以使用 Farid Haq 提到的解决方案 3,它通过做活动本身的工作来做同样的事情)

    这里Activity实现了回调OnDataUpdateListener

    interface OnDataUpdateListener{
        void passDataToFragmentB(String data)
    }
    

    活动代码:

    Fragment instanceFragmentB;
    // intialise it somewhere in your activity
    // or get from viewpager adapter
    
    @Override
    void passDataToFragmentB(String data){
        instanceFragmentB.onDataChange(data)
    }
    

    片段A代码:

    OnDataUpdateListener mOnDataUpdateListener;
    onAttach(Activity activity){
        mOnDataUpdateListener=  (OnDataUpdateListener) activity
    }
    
    onViewCreated(){
        somebutton.onClick{
            mOnDataUpdateListener.passDataToFragmentB("someString")
        }
    }
    

    片段B代码:

    onDataChange(String data){
        //do your work with update data passed from fragment A  
    }
    

    解决方案 2:使用 EventBus 或 RxBus

    //如果您的片段实例处于活动状态,这将起作用,因此请检查 viewpager offscreenpage limit

    使用 event 或 rxbus,在总线上发布新的更新值并使目标片段观察相同的值类型。

    片段 A:

    onViewCreated(){
        somebutton.onClick{
            EventBus.post("your data")
        }
    }
    

    片段 B:

    @Subsribe
    void onDataChange(String data){
        //do your work with update data passed from fragment A  
    }
    

    解决方案 3:使用 ViewModel。

    在所有片段中获取带有活动上下文的视图模型,并使用 LiveData 包装字符串。

    每当字符串数据发生变化时,只需在字符串 Livedata 对象上发布新数据即可。 所有观察到 livedata 的片段都将获得更新的值。

    【讨论】:

    • 检查屏幕外页面限制是什么意思?我把它设置为三个
    • 方法 1 在主要活动行返回空对象引用错误:instanceFragmentB.onDataChange(data)
    • 在这些方法中,如果您的屏幕外页面限制低于 1,并且如果您要更改第 1 页上的某些数据,则第 3 页片段将不会在内存中。所以它不会收到任何回调。因为当用户滚动并进入第二或第三屏幕时它将被初始化。 .... 对于 null 错误,请检查您如何获取 fragmentB 的实例,如果您正在使用适配器,请尝试从那里获取它。或者如果您从容器中获取当前片段并检查它是 FragmentB 的实例,然后在转换后调用 onDataChange 则更好。
    • 我采用了容器方法并将其添加到您的原始答案中,感谢您的帮助。这里有更多信息:stackoverflow.com/questions/15492717/…
    【解决方案2】:

    解决方案 1

    在你的 MainActivity 中

    @Override
    public void onDataReceived(String data) {
       Log.e(TAG, "MainActivity received this string " + data );
       Bundle bundle = new Bundle();
       bundle.putString("edttext", data);
       FragmentB fragment = new FragmentB();
       fragment.setArguments(bundle);
       // Fragment Transaction method goes here
    }
    

    在你的 FragmentB 中检索数据

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
       String strtext = getArguments().getString("edttext");    
       return inflater.inflate(R.layout.fragment, container, false);
    }
    

    解决方案 2

    您可以将回调数据放入您的全局变量中,并在 onClickListerner 时的片段事务中使用它。

    解决方案 3

    A) 在 FragmentB 中创建方法

    public void changeText (String data) {
       textview.setText(data)
     }
    

    B) 并从 MainActivity 传递值

    @Override
    public void onDataReceived (String data) {
        myInterface.CallBack("Callbacked when onCreate method Created" + data);
        Log.d("Tiggered", "respond: ");
        FragmentManager manager = getFragmentManager();
        FragmentB fragmentB = (FragmentB) manager.findFragmentById(R.id.id_fragmentB);
        fragmentB.changeText(data);
    }
    

    【讨论】:

    • 第一种方法我在片段 B 中得到一个空对象引用错误
    • java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“java.lang.String android.os.Bundle.getString(java.lang.String)”
    • 我不知道你是怎么做片段交易的。请尝试其他解决方案特别解决方案3。在您的 Fragment B 中创建方法,并直接传递值
    • 使用解决方案 3 我得到:静态方法 'CallBack(java.lang.String)' 不能从静态上下文中引用
    • 首先你需要知道inter通信片段的过程。有很多关于内部通信的在线文档。也有类似的帖子请查看stackoverflow.com/questions/13700798/…
    猜你喜欢
    • 1970-01-01
    • 2016-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-31
    • 2019-10-05
    相关资源
    最近更新 更多