【问题标题】:How to set up listeners nicely between fragments?如何在片段之间很好地设置监听器?
【发布时间】:2019-11-28 23:40:49
【问题描述】:

我有一个有 4 个选项卡的应用程序,都是 Fragments 并且有一个适配器,因为我使用的是 RecyclerView。在第一个选项卡上,我有项目。我希望第二个选项卡显示在第一个选项卡上检查的项目并听取更改。当我单击第一段上的按钮时,第三个选项卡显示来自第二个选项卡的项目(=第一个选项卡检查项目)。现在我在 onCreate 和 onCreateView 中设置监听器。有时它工作,有时没有。我怀疑创建方法不是每次都以相同的顺序执行。另一个问题是有时我的 Fragment 必须通知侦听器,有时是 Fragment 的适配器。如何善待它?

第一个标签(它的适配器会通知)

public class EventFragment extends Fragment implements BettingEventAdapter.BettingItemClickListener {

    private RecyclerView recyclerView;
    static private BettingEventAdapter adapter;
    private BettingListDatabase database;
    private static Answer bettingData = null;
    private static final String TAG = "EVENT";
    private static BettingEventAdapter.BettingItemClickListener listener;

    public static void setListener(BettingEventAdapter.BettingItemClickListener _listener) {
        listener = _listener;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        database = BettingListDatabase.getInstance(this.getContext());

        loadBettingData();

    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_events,
                container, false);

        recyclerView = view.findViewById(R.id.MainRecyclerView);
        adapter = new BettingEventAdapter(this);
        adapter.addBettingItemListener(listener);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity().getBaseContext()));
        recyclerView.setAdapter(adapter);

        loadItemsInBackground();

        return view;
    }

第二个标签:

public class TicketFragment extends Fragment implements BettingEventAdapter.BettingItemClickListener {

    private RecyclerView recyclerView;
    TextView prizeTextView;
    EditText stakeInput;
    Button bSave;

    private static BettingTicketAdapter.TicketSaveClickListener listener;
    private BettingListDatabase database;
    private BettingTicketAdapter adapter;
    double odds=1;
    int stake=0;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        database = BettingListDatabase.getInstance(this.getContext());
        EventFragment.setListener(this);
            }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_ticket,
                container, false);

        recyclerView = view.findViewById(R.id.TicketRecyclerView);
        adapter = new BettingTicketAdapter();
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity().getBaseContext()));
        recyclerView.setAdapter(adapter);
}

第三个标签:

public class TicketListFragment extends Fragment implements BettingTicketAdapter.TicketSaveClickListener {

    private BettingTicketListAdapter parentAdapter;
    private BettingListDatabase database;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        database = BettingListDatabase.getInstance(this.getContext());
        TicketFragment.setListener(this);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        super.onCreateView(inflater, container, savedInstanceState);

        View view = inflater.inflate(R.layout.fragment_ticket_list,
                container, false);
        RecyclerView parentRecyclerView = view.findViewById(R.id.SavedTicketParentRecyclerView);
        parentAdapter = new BettingTicketListAdapter();
       //TODO db-ből feltölteni
        loadItemsInBackground();
        parentRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity().getBaseContext()));
        parentRecyclerView.setAdapter(parentAdapter);

        return view;
    }

寻呼机活动:

public class PagerActivity extends AppCompatActivity {

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

    @Override
    protected void onResume() {
        super.onResume();
        ViewPager mainViewPager = findViewById(R.id.mainViewPager);
        TabPagerAdapter tabPagerAdapter = new TabPagerAdapter(getSupportFragmentManager(), this);
        mainViewPager.setAdapter(tabPagerAdapter);
    }
}

【问题讨论】:

  • 从技术上讲,当前推荐的解决方案是使用共享 ViewModel,它通过每个 Fragment 使用其viewLifecycleOwner 订阅的 LiveData 公开数据。

标签: java android fragment listener


【解决方案1】:

https://developer.android.com/training/basics/fragments/communicating

要允许 Fragment 与其 Activity 进行通信,您可以在 Fragment 类中定义一个接口并在 Activity 中实现它。 Fragment 在其 onAttach() 生命周期方法期间捕获接口实现,然后可以调用接口方法以与 Activity 通信。

这是您的片段的示例:

EventFragment

public class EventFragment extends Fragment {
    OnEventSelectedListener callback;

    public void setOnEventSelectedListener(OnEventSelectedListener callback) {
        this.callback = callback;
    }

    // This interface can be implemented by the Activity, parent Fragment,
    // or a separate test implementation.
    public interface OnEventSelectedListener {
        public void onEventSelected(int position);
    }

    // ...
}

PagerActivity

    public class PagerActivity extends AppCompatActivity implements EventFragment.OnEventSelectedListener{

    // ...

    // In order to receive event callbacks from the fragment, the activity that
    // hosts it must implement the interface defined in the fragment class.
    //For example, the following activity implements the interface from the above example.

    public void onEventSelected(int position) {
        // ...
    }

    @Override
    public void onAttachFragment(Fragment fragment) {
        if (fragment instanceof EventFragment) {
            EventFragment eventFragment = (EventFragment) fragment;
            eventFragment.setOnEventSelectedListener(this);
        }
    }
}

例如,当用户单击列表项时,会调用片段中的以下方法。 Fragment 使用回调接口将事件传递给父 Activity。

@Override
public void onListItemClick(ListView l, View v, int position, long id) {
    // Send the event to the host activity
    callback.onEventSelected(position);
}

【讨论】:

猜你喜欢
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
  • 2015-07-06
  • 2019-05-27
  • 2016-02-04
  • 2014-08-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多