我无法通过广播将数据发送到活动中的片段

Posted

技术标签:

【中文标题】我无法通过广播将数据发送到活动中的片段【英文标题】:I can't send data to a fragment from an activity with broadcast 【发布时间】:2020-06-22 17:48:59 【问题描述】:

我正在尝试将数据从活动发送到片段。数据是当前单击的项目的名称,我需要,因为我想进行查询。但数据永远不会发送。我也尝试在调用fragment.begingTrascation之前发送广播,但仍然不起作用, 我还更改了常量的名称,但仍然不会触发来自 Fragment 的广播。 我不知道为什么不起作用,我该怎么做才能解决这个问题?

    private NavigationView.OnNavigationItemSelectedListener navigationListener = new NavigationView.OnNavigationItemSelectedListener() 
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) 
        if (item.getItemId() == R.id.nav_today) 
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.fragment_container, new TodayFragment())
                    .commit();

         else if (item.getItemId() == R.id.nav_inbox) 
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.fragment_container, new InboxFragment())
                    .commit();

         else if (item.getItemId() == R.id.nav_add_list) 
            ListBottomSheet bottomSheet = new ListBottomSheet();
            bottomSheet.showNow(getSupportFragmentManager(), "bottomSheetList");

         else if (item.getItemId() == R.id.nav_account) 
            startActivity(new Intent(HomeDrawerActivity.this, AccountActivity.class));

         else if (item.getItemId() == R.id.nav_random_task) 
            startActivity(new Intent(HomeDrawerActivity.this, RandomTaskActivity.class));

         else 
            /* one of the list items
              was clicked therefore
              get the data form db
             */
            item.setCheckable(true);
            item.setChecked(true);
            String listName = item.getTitle().toString();
            Toast.makeText(HomeDrawerActivity.this, listName, Toast.LENGTH_LONG).show();

            /* create the fragment */

            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.fragment_container, new ListFragment())
                    .commit();

            /* send data to the fragment */

            Intent intent = new Intent(LIST_ACTION);
            intent.putExtra(KEY_LIST_NAME, listName);

            LocalBroadcastManager.getInstance(HomeDrawerActivity.this).sendBroadcast(intent);

        

        drawer.closeDrawer(GravityCompat.START);
        return true;
    
;

public class ListFragment extends Fragment 
private Context context;
private String documentName;

private ListAdaptor listAdaptor;
private RecyclerView recyclerViewList;

private ColorDrawable swipeBackgroundRight = new ColorDrawable(Color.parseColor("#FF0000"));
private ColorDrawable swipeBackgroundLeft = new ColorDrawable(Color.parseColor("#1E88E5"));

private Drawable iconDelete;
private Drawable iconComplete;

private SoundPool soundPool;
private int soundId;

private FirebaseFirestore firestore = FirebaseFirestore.getInstance();
private CollectionReference collectionReference = firestore.collection("Users")
        .document(FirebaseAuth.getInstance().getCurrentUser().getUid())
        .collection("Lists");

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) 
    View rootView = LayoutInflater.from(getActivity()).inflate(R.layout.list_fragment, container, false);

    LocalBroadcastManager.getInstance(context)
            .registerReceiver(broadcastReceiver, new IntentFilter(HomeDrawerActivity.LIST_ACTION));


    iconDelete = ContextCompat.getDrawable(getActivity(), R.drawable.ic_delete);
    iconComplete = ContextCompat.getDrawable(getActivity(), R.drawable.ic_completed);

    if (!TextUtils.isEmpty(documentName)) 
        collectionReference.document(documentName);

     else 
        Toast.makeText(getActivity(), "Error", Toast.LENGTH_SHORT).show();
    

     /* create the option query
        for the recycler
      */

    Query query = collectionReference;

    FirestoreRecyclerOptions<Task> options =
            new FirestoreRecyclerOptions.Builder<Task>()
                    .setQuery(query, Task.class)
                    .build();

    listAdaptor = new ListAdaptor(options);

    recyclerViewList = rootView.findViewById(R.id.recycler_view_list);
    recyclerViewList.setHasFixedSize(true);
    recyclerViewList.setLayoutManager(new LinearLayoutManager(getActivity()));
    recyclerViewList.setAdapter(listAdaptor);


    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 
        AudioAttributes audioAttributes =
                new AudioAttributes.Builder()
                        .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
                        .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                        .build();

        soundPool = new SoundPool.Builder()
                .setMaxStreams(1)
                .setAudioAttributes(audioAttributes)
                .build();

     else 
        soundPool = new SoundPool(1, AudioManager.STREAM_RING, 0);
    
    soundId = soundPool.load(getActivity(), R.raw.completed, 1);

    new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT) 
        @Override
        public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) 
            return true;
        

        @Override
        public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) 
            if (direction == ItemTouchHelper.RIGHT) 
                listAdaptor.delete(viewHolder.getAdapterPosition());
                Toast.makeText(context, "Task deleted", Toast.LENGTH_SHORT).show();
             else if (direction == ItemTouchHelper.LEFT) 
                listAdaptor.update(viewHolder.getAdapterPosition());

                soundPool.play(soundId, 1, 1, 1, 0, 1);

                Toast.makeText(context, "Task completed", Toast.LENGTH_SHORT).show();
                swipeBackgroundRight.setBounds(0, 0, 0, 0);
                iconDelete.setBounds(0, 0, 0, 0);
            
        

        @Override
        public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) 

            View itemView = viewHolder.itemView;
            int iconMargin = (itemView.getHeight() - iconDelete.getIntrinsicHeight()) / 2;
            if (dX > 0) 
                swipeBackgroundRight.setBounds(itemView.getLeft(), itemView.getTop(), (int) dX, itemView.getBottom());
                iconDelete.setBounds(itemView.getLeft() + iconMargin, itemView.getTop() + iconMargin, itemView.getLeft() + iconMargin + iconDelete.getIntrinsicWidth(), itemView.getBottom() - iconMargin);
             else if (dX < 0) 
                swipeBackgroundLeft.setBounds(itemView.getRight() + (int) dX, itemView.getTop(), itemView.getRight(), itemView.getBottom());
                iconComplete.setBounds(itemView.getRight() - iconMargin - iconComplete.getIntrinsicWidth(), itemView.getTop() + iconMargin, itemView.getRight() - iconMargin,
                        itemView.getBottom() - iconMargin);

             else 
                swipeBackgroundLeft.setBounds(0, 0, 0, 0);
                swipeBackgroundRight.setBounds(0, 0, 0, 0);

            
            c.save();

            swipeBackgroundRight.draw(c);
            swipeBackgroundLeft.draw(c);
            if (dX > 0) 
                c.clipRect(itemView.getLeft(), itemView.getTop(), (int) dX, itemView.getBottom());
             else 
                c.clipRect(itemView.getRight() + (int) dX, itemView.getTop(), itemView.getRight(), itemView.getBottom());
            

            iconDelete.draw(c);
            iconComplete.draw(c);
            c.restore();


            super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);

        
    ).attachToRecyclerView(recyclerViewList);

    return rootView;


@Override
public void onAttach(@NonNull Context context) 
    super.onAttach(context);


private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() 
    @Override
    public void onReceive(Context context, Intent intent) 
        if (HomeDrawerActivity.LIST_ACTION.equals(intent.getAction())) 

            /* get the data from db */

            documentName = intent.getStringExtra(HomeDrawerActivity.KEY_LIST_NAME);
            Toast.makeText(getActivity(), "List fragment" + documentName, Toast.LENGTH_LONG).show();

        
    
;

@Override
public void onStart() 
    super.onStart();
    listAdaptor.startListening();


@Override
public void onDestroyView() 
    super.onDestroyView();
    LocalBroadcastManager.getInstance(context).unregisterReceiver(broadcastReceiver);

【问题讨论】:

【参考方案1】:

如果您在Fragment 事务开始之前发送广播,Fragment 很可能无法及时设置其BroadcastReceiver 来捕捉传输。

但在您的情况下,您可以在开始事务之前将要传递给Fragment 的数据添加到ListFragment 实例的参数Bundle

String listName = item.getTitle().toString();

/* create the fragment */
ListFragment listFragment = new ListFragment();

/* store data in arguments Bundle */
Bundle args = new Bundle();
args.putString(KEY_LIST_NAME, listName);
listFragment.setArguments(args);

getSupportFragmentManager().beginTransaction()
                .replace(R.id.fragment_container, listFragment )
                .commit();

ListFragment,您可以通过如下方式访问数据:

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) 
    View rootView = LayoutInflater.from(getActivity()).inflate(R.layout.list_fragment, container, false);
    Bundle args = getArguments();
    String listName = args.getString(KEY_LIST_NAME);

    // ....

【讨论】:

尝试在空对象引用上调用虚拟方法'java.lang.String android.os.Bundle.getString(java.lang.String)' @Scepticul - 你使用 listFragment.setArguments(args);在开始交易之前? 是的,和你的例子一模一样。 @Scepticul - 感谢您告诉我,祝您项目顺利! 再次感谢您!

以上是关于我无法通过广播将数据发送到活动中的片段的主要内容,如果未能解决你的问题,请参考以下文章

将数据从片段发送到活动,无需任何事件处理或侦听器

将数据从活动发送到片段android工作室[重复]

如何将结果数据从广播接收器发送到活动

Java Android - 将数据从活动发送到片段

如何将字符串数据从活动发送到片段?

将数据从一个片段发送到另一个片段时出错。 (两个片段都由一个活动托管)