Android Fragments 列表项的片段?

z9ju0rcb  于 2023-01-17  发布在  Android
关注(0)|答案(1)|浏览(138)

我是Android开发的新手,在最佳实践方面有点挣扎。这是为了一个乐高蓝牙项目,但这在这里并不重要。
我已经创建了一个列表视图,可以有3个不同的项目。我的列表项目也有按钮,并从设备订阅更新。因此,我创建了一个自定义适配器:

public class DeviceListAdapter extends BaseAdapter {
    private final List<Device> devices;

    public DeviceListAdapter(List<Device> devices) {
        this.devices = devices;
    }

    @Override
    public int getItemViewType(int position) {
        Object item = getItem(position);

        if (item instanceof TrainHub) {
            return 0;
        } else if (item instanceof Remote) {
            return 1;
        } else {
            return 2;
        }
    }

    // MORE methods
    ...
    
    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        Device device = devices.get(i);

        // Disconnect the adapter if is associated to another device.
        boolean isDisconnected = Adapter.disconnect(view, device);

        int viewType = getItemViewType(i);

        if (view == null) {
            if (viewType == 0) {
                view = layoutInflater.inflate(R.layout.layout_train_item, viewGroup, false);
            } else {
                ...
            }
        }

        // Only create the adapter when necessary.
        if (isDisconnected) {
            if (viewType == 0) {
                new TrainHubAdapter((TrainHub)device, view, activity).connect();
            }
        }

        return view;
    }
}

我将代码缩短了一点。TrainHubAdapter创建实际模型(TrainHub)之间的绑定。我有点困惑为什么要多次调用该方法,因此我确保只在必要时创建适配器。
我想把我的应用的布局改为标签视图,我意识到有一个片段的概念,它处理生命周期管理。我认为这正是我需要的。我不想重新发明轮子,我认为这将给予我机会使用生命周期观察器等。
是否有列表适配器使用片段而不是视图?

hwazgwia

hwazgwia1#

我已经找到了解决方案。我需要一个 Package 器视图来托管我的片段。所以我将片段管理器传递给基础适配器,并根据列表中的实际项设置片段:

public class DeviceListAdapter extends BaseAdapter {
    private final List<Device> devices;
    private FragmentManager fragmentManager;

    public DeviceListAdapter(List<Device> devices, FragmentManager fragmentManager) {
        this.devices = devices;
        this.fragmentManager = fragmentManager;
    }
    
    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        if (view == null) {
            view = new FragmentContainerView(viewGroup.getContext());
            // The fragment is added by a view ID, therefore we have to generate a ID here.
            view.setId(View.generateViewId());
            view.setTag(i);

            view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
                @Override
                public void onViewAttachedToWindow(View view) {
                    // The fragment can only be set if the view is attached.
                    handleAttachedItem(view);
                }

                @Override
                public void onViewDetachedFromWindow(View view) {

                }
            });
        }

        if (view.isAttachedToWindow()) {
            handleAttachedItem(view);
        }

        return view;
    }

    private void handleAttachedItem(View view) {
        int viewIndex = (int) view.getTag();
        int viewType = getItemViewType(viewIndex);
        Device device = devices.get(viewIndex);

        Fragment fragment = getFragment(view);

        if (fragment == null || !IsCorrectFragment(viewType, fragment)) {
            FragmentTransaction transaction = fragmentManager.beginTransaction();

            if (viewType == 0) {
                TrainHubAdapter trainHubAdapter = new TrainHubAdapter();
                
                transaction.replace(view.getId(), trainHubAdapter);
            } else {
                ....
            }

            transaction.commit();
        }

        Adapter adapter = (Adapter) getFragment(view);

        if (adapter != null) {
            adapter.setDevice(device);
        }
    }

    private Fragment getFragment(View view) {
        try {
            return FragmentManager.findFragment(view);
        } catch (IllegalStateException ex) {
            return null;
        }
    }

    private boolean IsCorrectFragment(int viewType, Fragment fragment) {
        if (viewType == 0) {
            return fragment.getClass() == TrainHubAdapter.class;
        } else {
            ....
        }
    }
}

我认为,从技术上讲,列表现在只有一个条目类型,因此我们可以删除如下方法:

@Override
    public int getItemViewType(int position) {
        ...
    }

    @Override
    public int getViewTypeCount() {
        return 3;
    }

相关问题