搜尋

首頁  >  問答  >  主體

android的ListView点击事件问题?

当我在写一个android应用的时候遇到了这样一个需求:

有个ListView,里面的item都有图片和文字,当一个item被点击的时候显示在此item上显示图片和一个进度条,当另一个item被点击的时候隐藏上一次被电击item的图片和进度条,显示当前被点击item的图片和进度条

我的有关代码是这样的,用的是simpleAdapter

我的思路是就这样的,先把ListView的所有item遍历,隐藏我该隐藏的控件,然后显示当前被点击item的要显示的控件(progressbar和playing_effect)

不过问题出现了,点击之后的效果特别卡,不知道怎么回事点击40-50次之后就出现手机内存不足的情况,难道我的思路一开始是错误的吗?还是需要优化?耗内存是怎么回事啊

谢谢






public class MainActivity extends AppCompatActivity {



    ArrayList<Boolean> itemState = new ArrayList<>();
    int checkedItemIndex = -1;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        for (int s=0;s<20;s++){
            itemState.add(false);
        }


        class AudioListAdapter extends SimpleAdapter{

            public AudioListAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to) {
                super(context, data, resource, from, to);
            }
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                View v = super.getView(position, convertView, parent);
                //
                if (itemState.get(position)){
                    // 设置点击状态
                    v.findViewById(R.id.progressBar).setVisibility(View.VISIBLE);
                    v.findViewById(R.id.playing_effect).setVisibility(View.VISIBLE);
                }else {
                    // 设置未点击状态
                    v.findViewById(R.id.progressBar).setVisibility(View.GONE);
                    v.findViewById(R.id.playing_effect).setVisibility(View.GONE);
                }
                //

                return v;
            }
        }



        final ArrayList<HashMap<String, Object>> listItem = new ArrayList<HashMap<String, Object>>();
        for (int i = 0; i < 10; i++){
            HashMap<String,Object> map = new HashMap<String, Object>();
            map.put("song","song name "+i);
            map.put("singer","singer "+i);
            map.put("currentTime","01:3"+i);
            map.put("allTime","04:5"+i);

            listItem.add(map);
        }

        final ListView listView = (ListView)findViewById(R.id.listView);
        final AudioListAdapter audioListAdapter = new AudioListAdapter(
                this,
                listItem,
                R.layout.item,
                new String[]{"song","singer","currentTime","allTime"},
                new int[]{R.id.song,R.id.singer,R.id.currentTime,R.id.allTime}
        );

        listView.setAdapter(audioListAdapter);

        // onclick
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                //
                if (checkedItemIndex>=0){
                    itemState.set(checkedItemIndex,false);
                }
                checkedItemIndex = position;
                itemState.set(position,true);
                audioListAdapter.notifyDataSetChanged();
                //
            }
        });

    }

    @Override
    public void onStart(){
        super.onStart();
    }

}

上面我把所有代码给贴出来的,我按楼下回复里的想法去做的,我发现结果同样很卡,内存耗得更快,大神们看一下吧

谢谢

天蓬老师天蓬老师2772 天前380

全部回覆(4)我來回復

  • PHP中文网

    PHP中文网2017-04-17 17:43:00

    樓上兩位已經說的比較清楚了,自己維護一個列表,然後在getView中根據列表的狀態繪製不同的View。
    之前你的方法需要遍歷並創建所有itemView的實例,無論是對cpu還是內存都有很大的壓力,所以會卡,在item數量未知的前提下最好不要遍歷,保存一個上次點擊的index就行了。
    隨便寫了些偽代碼,大概是這樣的

     ArrayList<Boolean> list = new ArrayList<>();
     int listClickedItemIndex = -1;
        public View getView(int position, View convertView, ViewGroup parent) {
            if(list.get(position)){
                //设为点击状态
            }else{
                //设为未点击状态
            }
            return convertView;
        }
        public void onItemClick(int position){
           if(listClickedItemIndex >= 0){
               list.set(listClickedItemIndex,false);
           }
            listClickedItemIndex = position;
            list.set(position,true);
            adapter.notifyDataSetChanged();
        }

    ----------------------------分割線------------------- --
    你getView部分的程式碼有問題,在這裡你應該建立/重複使用convertView

    回覆
    0
  • 怪我咯

    怪我咯2017-04-17 17:43:00

    我說下我的思路吧:
    把item的點擊狀態都存在adapter中,每次點擊只要去更新adapter中具體item的某個屬性就行了。接著在getView裡根據這個屬性的不同做不同的處理。

    回覆
    0
  • 天蓬老师

    天蓬老师2017-04-17 17:43:00

    把顯示/隱藏的邏輯寫在listView的adapter的getView方法,點擊的時候呼叫notifyDataSetChanged就可以了

    回覆
    0
  • 黄舟

    黄舟2017-04-17 17:43:00

    3樓正解,自己新建一個boolean類型的list用以保存每個item的狀態,每次點擊先將下標currentitemindex的item屬性改為false,將下標position的item屬性設為true。然後更新curreentitemindex.最後刷新adapter

    回覆
    0
  • 取消回覆