Android 动态表单中遇到的问题

项目中要做一个动态表单,就是根据后台返回的json数据来生成界面,然后把用户录入的值返回给后台。界面效果如下:

关于动态表单,其实相当于后台去控制App界面显示。这篇文章解释的不错,大家可以去看看。Android 动态表单新解

\qquad 刚开始做的时候想着既然是列表,那么应该用RecyclerView,于是配合着BRVAH,用多布局的方式实现了。当然还得处理控件复用的问题,包括但不限于EditText、RadioGroup、CheckBox这些。颇费了一番功夫。处理完后测了一下,上下滑动、数据回显什么的都正常。

	//一段处理EditText复用的代码
    private void recycleEditText(@NonNull BaseViewHolder helper, CheckItemApi.DataBean.ContentBean childPhysicalBean, EditText editText, ImageView iv_status) {
        editText.setEnabled(childPhysicalBean.isCanEdit());
        editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                //可以根据需求获取下一个焦点还是上一个
                View nextView = v.focusSearch(View.FOCUS_DOWN);
                if (nextView != null) {
                    nextView.requestFocus(View.FOCUS_DOWN);
                }
                return true;
            }
        });
        if (childPhysicalBean.isCanEdit()) {
            editText.setHint("请输入");
        }
        ···
        editText.setInputType(childPhysicalBean.getInputType());
        TextWatcher tag = (TextWatcher) editText.getTag(R.id.text_watcher);
        if (null != tag) {
            editText.removeTextChangedListener(tag);
        }
        TextWatcher watcher = new TextWatcher() { ··· };
        editText.setTag(R.id.text_watcher, watcher);
        editText.addTextChangedListener(watcher);
    }

\qquad 过了一段时间,当有个人在6年前的平板上使用时,问题出现了,滑动很卡顿。检查了代码,问题应该出在包含RadioButton、CheckBox这些控件的item身上,因为这些item都是动态添加的的,每次都得removeAllviews addview…

case CHOICE_SINGLE:
	RadioGroup h_rg_layout = helper.getView(R.id.rg_layout);
	h_rg_layout.removeAllViews();
	ArrayList<DictionaryBean> h_lists = JsonParser.getMMkvDictBeanFromKey(childPhysicalBean.dictType);
	if (!h_lists.isEmpty()) {
		for (DictionaryBean dictionaryBean : h_lists) {
			RadioButton radioButton = new RadioButton(mContext);
			radioButton.setEnabled(childPhysicalBean.isCanEdit());
			···
			radioButton.setId(View.generateViewId());
			if (!TextUtils.isEmpty(childPhysicalBean.inputContent)
					&& childPhysicalBean.inputContent.equals(dictionaryBean.value)) {
				radioButton.setChecked(true);
			}
			h_rg_layout.addView(radioButton);
		}
	}
	break;

\qquad 然后搜了一堆解决方案,什么禁止复用、设置ViewHolder缓存之类的。并没有找到太好的方法。

	rv_list.setItemViewCacheSize(20);

\qquad 加大缓存是有效果,不过这样做岂不是失去RecyclerView的意义了,那还不如用ViewGroup去addView。于是我就用LinearLayout重写了,还不用处理复用。并且也没有滑动卡顿的问题,就是数据量多的时候,加载慢了一点,因为我是全部数据一次性解析生成的,RecyclerView可以只绘制屏幕可见范围的数据。不过Layout也可以优化一下,把数据分割,分次加载。

for (int indexB = 0; indexB < beanArrayList.size(); indexB++) {
	CheckItemApi.DataBean.ContentBean childPhysicalBean = beanArrayList.get(indexB);
	View inflate = null;
	switch (childPhysicalBean.getItemType()) {
		case EDIT:
			inflate = LayoutInflater.from(mContext)
					.inflate(R.layout.content_edit, ll_root, false);
			// 给item布局设置个tag 用来局部刷新
			inflate.setTag(childPhysicalBean.name);
			setText(inflate, R.id.tv_unit, childPhysicalBean.unit)
					.setGone(inflate, R.id.tv_unit, !TextUtils.isEmpty(childPhysicalBean.unit));
			break;
		···
	}
	if (inflate != null) {
		ll_root.addView(inflate);
	}
}
···
// 使用findViewWithTag方法配合inflate时候设置的tag,实现类似RecyclerView的局部刷新item功能
public void refreshData(ViewGroup ll_root, CheckItemApi.DataBean.ContentBean childPhysicalBean) {
	View viewWithTag = ll_root.findViewWithTag(childPhysicalBean.name);
	if (null == viewWithTag) {
		return;
	}
	switch (childPhysicalBean.getItemType()) {
		case EDIT:
			EditText editText = viewWithTag.findViewById(R.id.et_input);
			editText.setText(childPhysicalBean.getInputContent());
			break;
	}
}
后记

\qquad 因为我们数据量不多,就是一份体检表单,最多几百个view,所以基本没什么内存问题,add view比RecyclerView更适合。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值