当RecyclerView处于Fragment中时,我不能全神贯注于如何更新RecyclerView显示的数据。我有一个字符串数组列表,这是我要显示的成员存储的地方。如果我在Fragment脚本或Fragment所在的main-activity中预定义了列表,它将很好地显示在RecyclerView上。但是后来我尝试在运行时更新列表,我完全迷失了。如何在运行时更新列表?
在我的应用程序中,我试图扫描该区域中的BT设备,并将扫描结果显示在此RecyclerView上。我知道扫描部分工作正常,我可以得到一个字符串数组列表,其中包含该区域中所有扫描设备的MAC地址。我尝试通过设置器将更新的数据传递给Fragment脚本,但是当到达代码中的该点时,它会崩溃。
//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();
}
}
如上所述,我希望Fragment中保存的RecyclerView可以显示String ArrayList的内容,该内容将从main-activity中更新。我已经下线了,几天来一直在努力解决这个问题!
答案 0 :(得分:0)
在您的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();
}
因此,您现在不需要在片段中使用notifyDatasetChanged。