首页 > 解决方案 > 如何更新 recyclerview 显示的数据,这些数据包含在主要活动的片段中?

问题描述

当 RecyclerView 位于 Fragment 中时,我不知道如何更新 RecyclerView 显示的数据。我有一个 ArrayList of Strings,这是我要显示的成员的存储位置。如果我在 Fragment 脚本或托管 Fragment 的主要活动中预定义了列表,它将很好地显示在 RecyclerView 上。但是后来我尝试在运行时更新列表,我完全迷失了。如何在运行时更新列表?

在我的应用程序中,我正在尝试扫描该区域中的 BT 设备并将扫描结果显示到此 RecyclerView 上。我知道扫描部分工作正常,我可以获得一个字符串数组列表,其中包含该区域中所有扫描设备的 MAC 地址。我尝试通过设置器将更新的数据传递给片段脚本,但是当它到达代码中的那个点时它会崩溃。

//This is what I use to define each device    
public class Device{
    private String deviceName;
    public Device(String name){
        this.deviceName = name;
    }
}

//----------------------------------------
//This is the adapter for the RecyclerView
public class deviceAdapter extends RecyclerView.Adapter<deviceAdapter.ViewHolder>{
    private List<Device> deviceList;
    public deviceAdapter(List<Device> deviceList){
        this.deviceList= deviceList;
    }

    //>>>>Data is set here<<<<
    public void setData(List<Device> deviceList) {
        this.deviceList = deviceList;
        notifyDataSetChanged();
    }

    public class ViewHolder extends RecyclerView.ViewHolder{
        public TextView deviceTextView;
        public Button connectButton;
        public ViewHolder(View itemView){
            super(itemView);
            deviceTextView = (TextView) itemView.findViewById(R.id.deviceDescription);
            connectButton = (Button)itemView.findViewById(R.id.connectButton);
        }
    }

    @Override
    public deviceAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        Context context = parent.getContext();
        LayoutInflater inflater = LayoutInflater.from(context);
        View deviceItemLayout = inflater.inflate(R.layout.deviceitem, parent, false);
        ViewHolder viewHolder = new ViewHolder(deviceItemLayout);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(deviceAdapter.ViewHolder viewHolder, int position) {
        viewHolder.deviceTextView.setText(deviceList.get(position).getName());
    }

    @Override
    public int getItemCount() {
        return data.length;
    }

//---------------------------------------
//Fragment that contains the RecyclerView
public class HomeFragment extends Fragment {
    private List<Device> deviceList = new ArrayList<>();
    //>>>> Adapter is created here<<<<
    deviceAdapter adapter = new deviceAdapter(deviceList);
    RecyclerView rvDevices;
    public HomeFragment(List<Device> deviceList){
        this.deviceList = deviceList;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
        View rootView = inflater.inflate(R.layout.fragment_home, container, false);
        rvDevices = (RecyclerView) rootView.findViewById(R.id.rvDevices);
        rvDevices.setLayoutManager(new LinearLayoutManager(getContext()));
        rvDevices.addItemDecoration(new DividerItemDecoration(rvDevices.getContext(), DividerItemDecoration.VERTICAL));
        //>>>>Adapter is set here<<<<
        rvDevices.setAdapter(adapter);
        rvDevices.setItemAnimator(new DefaultItemAnimator());
        return rootView;
    }

    public void updateFragmentData(List<Device> deviceL){
        this.deviceList = deviceL;
        if(adapter != null){
            adapter.setData(deviceList);
            adapter.notifyDataSetChanged();
        }
    }
}

//-------------------------------------------------
//my main-activity (relevant parts)
public class Interface extends AppCompatActivity {
    //Located at onCreate()
    homeFragment = new HomeFragment(scannedDevicesMAC);
    fragment = homeFragment
    fragmentManager = getSupportFragmentManager();
    fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction.replace(R.id.frameLayout, fragment);
    fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
    fragmentTransaction.commit();

    tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener(){
        @Override
        public void onTabSelected(TabLayout.Tab tab){
            switch(tab.getPosition()){
                case 0:
                    fragment = homeFragment;
                    break;
                case 1:
                    fragment = new JavaFragment();
                    break;
                case 2:
                    fragment = new AndroidFragment();
                    break;
            }

        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.frameLayout, fragment);
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        ft.commit();
        }
    //...
    });

    final BroadcastReceiver mReceiver = new BroadcastReceiver(){
        @Override
        public void onReceive(Context context, Intent incoming)
        {
            String iAction = incoming.getAction();
            if(BluetoothDevice.ACTION_FOUND.equals(iAction)){
                BluetoothDevice tmpScannedDevices = incoming.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                String tmpMACAddress = tmpScannedDevices.getAddress();
                int tmpRSSI = incoming.getShortExtra(BluetoothDevice.EXTRA_RSSI,Short.MIN_VALUE);
                String tmpDeviceName = tmpScannedDevices.getName();

                scannedDevicesBTOs.add(tmpScannedDevices);
                scannedDevicesMAC.add(new Device(tmpMACAddress));

                //This is the list I'm trying to display
                scannedDevicesList.add("Name: " + tmpDeviceName + " || Address: " + tmpMACAddress + " || RSSI:" + tmpRSSI);   
                if(fragment != null){
                    homeFragment.updateFragmentData(scannedDevicesMAC);
                }
            }
        }
    };

    public void scanDevices(){
        if(mBTAdapter.isEnabled()){
            scannedDevicesList.clear();
            scannedDevicesMAC.clear();
            scannedDevicesBTOs.clear();
            if(mBTAdapter.isDiscovering()){
                mBTAdapter.cancelDiscovery();
            }
            Log.d("scanDevices|scanDevices", "Scanning for BT devices");
            mBTAdapter.startDiscovery();
    }
}

如前所述,我希望片段中的 RecyclerView 显示正在从主活动更新的字符串 ArrayList 的内容。我排在最后,几天来一直在努力解决这个问题!

标签: androidandroid-fragmentsandroid-activityandroid-recyclerviewupdates

解决方案


在您Fragment创建下面的功能

public void updateFragmentData(Device[] data){
  this.data = data;
  if(adapter != null){
    adapter.setData(data);
    adapter.notifyDataSetChanged();
  }
}

然后从你的Activity电话

if(fragment != null){
   fragment.updateFragmentData(data);
}

以上是一个快速的解决方案。更好的方法是使用接口来更新fragment.

更新

在您的活动中,您应该声明这三个

HomeFragment homeFragment;
JavaFragment javaFragment;
AndroidFragment androidFragment;

然后在onCreate()初始化它们

homeFragment = new HomeFragment(data);
javaFragment = new JavaFragment();
androidFragment = new AndroidFragment();

然后你只需要更新,homeFragment所以代码看起来像这样

if(homeFragment != null){
  homeFragment.updateFragmentData(data);
}


public void setData(List<Device> deviceList) {
    this.deviceList.clear;
    this.deviceList.addAll(deviceList);

    notifyDatasetChanged();
}

所以你现在不需要在你的片段中通知DatasetChanged。


推荐阅读