listview自己制造bug分析如何解决

网上很多listview加载不同的布局 采用getItemViewType 方式行不通 也不知道他们怎么写的blog.能先自己用一下在发表吗 复制粘贴的东西 不自己分析对错,就这么用吗?

采用所有类型整合到一个item中控制布局显示隐藏的方式,虽然维护不方便,但至少不会出错。

我为了测试,使用了pulltorefreshlistview ,我的blog有讲。

错误源代码:

public class MainActivity extends AppCompatActivity {


    PullToRefreshListView listView;
    ImageView imageView;
    MyAdapter mAdapter;
    List<MDTO> list = new ArrayList<>();

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageView = (ImageView) findViewById(R.id.iv);

        imageView.setImageResource(R.drawable.proxyimg);

        //控件
        listView = (PullToRefreshListView) findViewById(R.id.listview);

        for (int i = 0; i < 50; i++) {
            MDTO mdto = new MDTO();
            mdto.setId(R.drawable.ic_launcher);
            mdto.setText("text" + i);
            mdto.setType(i % 3);
            list.add(mdto);
        }

        mAdapter = new MyAdapter(list);
        listView.setAdapter(mAdapter);


        //控件模式
        listView.setMode(PullToRefreshBase.Mode.PULL_FROM_START);

        //控件滚动行为
        listView.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView absListView, int i) {

            }

            @Override
            public void onScroll(AbsListView absListView, int i, int i1, int i2) {

            }
        });
        //控件刷新行为
        listView.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener<ListView>() {
            @Override
            public void onRefresh(PullToRefreshBase<ListView> refreshView) {

            }
        });

    }


    class MyAdapter extends BaseAdapter {

        List<MDTO> mList = new ArrayList<>();

        MyAdapter(List<MDTO> mdtoList) {

            mList.clear();
            this.mList.addAll(mdtoList);

            for (int i = 0; i < mList.size(); i++) {

                Log.i("id", mList.get(i).getId() + "");
                Log.i("type", mList.get(i).getType() + "");

            }

            notifyDataSetChanged();
        }

        @Override
        public int getCount() {
            return mList.size();
        }

        @Override
        public Object getItem(int i) {
            return mList.get(i);
        }

        @Override
        public long getItemId(int i) {
            return i;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {

            int type = mList.get(i).getType();
            ViewHolder_One viewHolder_one;

            if (view == null) {

                view = LayoutInflater.from(MainActivity.this).inflate(R.layout.item_one, null);
                viewHolder_one = new ViewHolder_One();
                viewHolder_one.iv = (ImageView) view.findViewById(R.id.one_iv);
                viewHolder_one.tv = (TextView) view.findViewById(R.id.one_tv);

            } else {

                viewHolder_one = (ViewHolder_One) view.getTag();

            }

            if (type == 0) {

                viewHolder_one.iv.setVisibility(View.VISIBLE);
                viewHolder_one.tv.setVisibility(View.VISIBLE);
                viewHolder_one.iv.setImageResource(mList.get(i).getId());
                viewHolder_one.tv.setText(mList.get(i).getText());
                view.setBackgroundColor(Color.RED);

            } else if (type == 1) {
                viewHolder_one.tv.setVisibility(View.VISIBLE);
                viewHolder_one.iv.setVisibility(View.GONE);
                viewHolder_one.tv.setText(mList.get(i).getText());
                view.setBackgroundColor(Color.BLUE);
            } else {
                viewHolder_one.iv.setVisibility(View.VISIBLE);
                viewHolder_one.tv.setVisibility(View.GONE);
                viewHolder_one.iv.setImageResource(mList.get(i).getId());
                view.setBackgroundColor(Color.WHITE);
            }

            return view;
        }

        class ViewHolder_One {
            TextView tv;
            ImageView iv;
        }

    }

}

当然 熟悉的同学一眼就看出问题所在,如果你忘了那么办呢?

报错处

java.lang.NullPointerException: Attempt to read from field 'android.widget.TextView com.lcldream.www.MainActivity$MyAdapter$ViewHolder_One.tv' on a null object reference
                                                                      at com.lcldream.www.MainActivity$MyAdapter.getView(MainActivity.java:141)
                                                                      at android.widget.HeaderViewListAdapter.getView(HeaderViewListAdapter.java:220)
                                                                      at android.widget.AbsListView.obtainView(AbsListView.java:2575)
                                                                      at android.widget.ListView.makeAndAddView(ListView.java:1956)
                                                                      at android.widget.ListView.fillDown(ListView.java:757)
                                                                      at android.widget.ListView.fillGap(ListView.java:721)
                                                                      at android.widget.AbsListView.trackMotionScroll(AbsListView.java:5733)
                                                                      at android.widget.AbsListView.scrollIfNeeded(AbsListView.java:3780)
                                                                      at android.widget.AbsListView.onTouchMove(AbsListView.java:4277)
                                                                      at android.widget.AbsListView.onTouchEvent(AbsListView.java:4052)
                                                                      at android.widget.ListView.onTouchEvent(ListView.java:4287)
                                                                      at android.view.View.dispatchTouchEvent(View.java:8677)
                                                                      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2517)
                                                                      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2161)
                                                                      at com.handmark.pulltorefresh.library.PullToRefreshListView$InternalListView.dispatchTouchEvent(PullToRefreshListView.java:312)
                                                                      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2523)
                                                                      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2175)
                                                                      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2523)
                                                                      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2175)
                                                                      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2523)
                                                                      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2175)
                                                                      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2523)
                                                                      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2175)
                                                                      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2523)
                                                                      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2175)
                                                                      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2523)
                                                                      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2175)
                                                                      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2523)
                                                                      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2175)
                                                                      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2523)
                                                                      at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2175)
                                                                      at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2539)
                                                                      at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1807)
                                                                      at android.app.Activity.dispatchTouchEvent(Activity.java:2823)
                                                                      at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:71)
                                                                      at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2496)
                                                                      at android.view.View.dispatchPointerEvent(View.java:8883)
                                                                      at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4779)
                                                                      at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4611)
                                                                      at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4087)
                                                                      at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4140)
                                                                      at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4106)
                                                                      at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4243)
                                                                      at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4114)
                                                                      at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4300)
                                                                      at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4087)
                                                                      at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4140)
                                                                      at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4106)
                                                                      at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4114)
                                                                      at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4087)
                                                                      at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6598)
                                                                    at a

我们一看 空指针 果断debug,debug是遇到任何问题都首先想到的。

进入了else{
viewHolder_one = (ViewHolder_One) view.getTag();
}
然后执行
对应type
报的空指针
那么至此问题定位就明确了
viewHolder_one 出问题了
我们在看viewholder代码发现没有setTag.添上再运行 很流畅。

那么没有tag为什么会报错呢 第一屏为什么没有报错呢?
涉及到listview复用机制
listview 为了达到优化目的 使用了复用机制 其实第一屏都是 执行view == null 判断 都是重新加载布局 第二屏开始慢慢移除旧的 此时 view不再为空 所以会重用tag中的内容,类似于日历表 可以上下滑动 但是 中间显示就一个 也就是容量有限 不用的就回收。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值