关于android:利用接口实现-Fragment-与-Activity-的通信机制

8次阅读

共计 5065 个字符,预计需要花费 13 分钟才能阅读完成。

引言

为了重复使用 Fragment 界面组件,您应将每个组件构建为一个齐全独立的模块化组件,定义它本人的布局和行为。定义这些可重用的 Fragment 后,您能够将它们与 Activity 相关联,并将其与应用逻辑相关联以实现整个复合界面。

您常常须要一个 Fragment 与另一个 Fragment 通信,比方为了依据用户事件更改内容。所有 Fragment 到 Fragment 的通信都是通过共享的 ViewModel 或关联的 Activity 来实现的。两个 Fragment 绝不能间接通信。

如需在 Fragment 之间通信,倡议创立一个共享的 ViewModel 对象。两个 Fragment 都能够通过所在的 Activity 拜访 ViewModel。Fragment 可在 ViewModel 内更新数据,如果应用 LiveData 公开该数据,新状态会被推送至其余 Fragment(只有它正在从 ViewModel 察看 LiveData)。要理解如何实现这种通信机制,请参阅 ViewModel 指南中的“在 Fragment 之间共享数据”局部。

如果无奈应用共享的 ViewModel 在 Fragment 之间进行通信,能够应用接口手动实现通信机制。然而,这种形式最终须要实现更多的工作,并且无奈在其余 Fragment 中轻松重用。

以上这段文字来自 Android 官网文档中 Fragment 这一章节,以下实例咱们是用接口手动实现通信机制的。

一、前言

<font face = 黑体 > 在 Fragment 与 Activity 之间的通信 这篇博客中,咱们提了一下 Fragment 与 Activity 之间的最佳通信形式,然而咱们没有深刻的解说,这篇博文咱们就联合例子来讲一下这个常识。咱们先来看一下咱们明天的要做的实例的成果:

<font face = 黑体 > 这个实例就是一个 Activity 外面有两局部,这两局部别离加载了两个 Fragment,下面那个蕴含 EditText 的 Fragment 每次输出完数据后,按下回车键,要将数据在上面那个 ListFragment 外面展现进去,这就波及到了 Fragment 与 Fragment 之间的通信。

二、ListFragment 简略介绍

  • <font face = 黑体 >ListFragment 蕴含一个 ListView;
  • <font face = 黑体 > 应用 SimpleAdapter 或者 SimpleCursorAdapter 作为适配器;
  • <font face = 黑体 > 间接应用 ListFragment 的 setListAdapter() 来设置适配器。

三、实现步骤

3.1、新建 Activity 并动态增加两个 Fragment

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".Index4Activity">
    
    <fragment
        android:id="@+id/fragment_new_item"
        android:name="com.zjgsu.fragmentdemo.fragment.NewItemFragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <fragment
        android:id="@+id/fragment_to_do_list"
        android:name="com.zjgsu.fragmentdemo.fragment.ToDoListFragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

3.2、监听 EditText 的回车事件并获取数据

<font face = 黑体 > 这个办法就间接在 Fragment 的 onCreateView() 外面实现了,具体代码如下所示(残缺代码文末给出):

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.fragment_new_item, container, false);
    final EditText newItem = view.findViewById(R.id.et_new_item);
    // 绑断按下操作
    newItem.setOnKeyListener(new View.OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {if (event.getAction() == KeyEvent.ACTION_DOWN) {
                // 判断回车键
                if (keyCode == KeyEvent.KEYCODE_ENTER) {String content = newItem.getText().toString();
                    // 调用接口中的办法
                    onNewItemAddListener.newItemAdded(content);
                    newItem.setText("");
                    return true;
                }
            }
            return false;
        }
    });
    return view;
}

3.3、利用接口传递数据到附着的 Activity 中

<font face = 黑体 > 在获取到 EditText 输出的数据后, 咱们须要利用接口的形式将数据传递给其附着的 Activity。之所以要利用接口的形式先将数据传递给 Activity,而不是间接在 Fragment 外面利用附着的 Activity 获取到上面的 ListFragment 就是为理解耦合。 即 Fragment 与 Activity 通信、Fragment 与另外一个 Fragment 通信,都应该依附他们所附着的 Activity 来实现通信代码,而不是在 Fragment 间接取得这个援用来实现业务代码

public class NewItemFragment extends Fragment {

    // Fragment 与 Activity 通信
    // Fragment 与 另外一个 Fragment 通信
    // 都应该依附他们所附着的 Activity 来实现通信代码,而不是在 Fragment 间接取得这个援用来实现业务代码

    // 申明一个接口,定义你要向 Activity 传递的办法
    public interface OnNewItemAddListener {public void newItemAdded(String content);
    }

    // 申明一个接口援用变量
    private OnNewItemAddListener onNewItemAddListener;

    @Override
    public void onAttach(@NonNull Context context) {super.onAttach(context);
        // 要求该 Fragment 所附着的 Activity 必须实现这个办法
        onNewItemAddListener = (OnNewItemAddListener) context;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.fragment_new_item, container, false);
        final EditText newItem = view.findViewById(R.id.et_new_item);
        // 绑定按下操作
        newItem.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {if (event.getAction() == KeyEvent.ACTION_DOWN) {
                    // 判断回车键
                    if (keyCode == KeyEvent.KEYCODE_ENTER) {String content = newItem.getText().toString();
                        onNewItemAddListener.newItemAdded(content);
                        newItem.setText("");
                        return true;
                    }
                }
                return false;
            }
        });
        return view;
    }
}

3.4、在 Activity 中实现接口并将数据增加到 ListFragment 中

<font face = 黑体 > 在 Activity 中咱们须要实现上述 Fragment 定义的接口获取数据,而后将数据增加到 ListFragment 中。

public class Index4Activity extends AppCompatActivity implements NewItemFragment.OnNewItemAddListener {

    /**
     * ListView
     * Adapter
     * data
     */

    // 数据源
    private ArrayList<String> data;
    // 适配器
    private ArrayAdapter<String> adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_index4);

        // 初始化
        data = new ArrayList<>();

        // 构建适配器
        adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, data);

        // 在 Activity 中取得其管辖的 Fragment
        ToDoListFragment fragment = (ToDoListFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_to_do_list);
        if (fragment != null) {fragment.setListAdapter(adapter);
        }
    }

    @Override
    public void newItemAdded(String content) {
        // 构建数据源
        data.add(content);
        adapter.notifyDataSetChanged();}
}

<font face = 黑体 >ToDoListFragment 的代码如下所示:

public class ToDoListFragment extends ListFragment {

    @Override
    public void onListItemClick(@NonNull ListView l, @NonNull View v, int position, long id) {super.onListItemClick(l, v, position, id);

        Toast mToast = Toast.makeText(getActivity(), "第" + (position + 1) + "项被选中了.", Toast.LENGTH_SHORT);
        mToast.setGravity(Gravity.CENTER, 0, 0);
        mToast.show();}
}

四、源码

<font face = 黑体 > 源码曾经上传至 github。下一篇博客咱们来讲一个用 Fragment 实现的繁难新闻实例,并适配手机和 pad。

正文完
 0