写点什么

Android 关于 ListView 知识点,Android 面试题集锦

作者:嘟嘟侠客
  • 2021 年 11 月 27 日
  • 本文字数:5363 字

    阅读完需:约 18 分钟

flag=0;


break;


}


}


});


list.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){


public void onItemSelected(AdapterView<?> parent, View view, int position, long id){


System.out.println(names[position]+"选中");


}


public void onNothingSelected(AdapterView<?> parent){


}


});


}


}



二. ListView 局部刷新


对 ListView 有了基本的了解,了解到在 Android 开发中我们经常会用到 listview 的数据和界面刷新动作,我们基本上用到的都是 Adapter.notifyDataSetChanged()方法。这个方法的原理是利用观察者模式对我们的数据源进行监听,当我们的数据源发生变化的时候,会调用 Adapter 的 getView()方法进行整个界面的刷新。getview()会调用多次,刷新了好多个不需要刷新的 item,这样的话相对而言,降低了效率。但是,我们有的情况下是只需要对某个 item 的数据进行刷新就可以了。如点击下图中的任一条目可以实现局部刷新,而不会全部刷新。



1.ListView 实现局部刷新方法一: 更的新对应 view 的内容 这种方法先通过 listView.getChild(position)拿到要更新的对应的 item 布局文件,然后再通过 findViewById 找到对应的控件进行设置。


package cn.bluemobi.dylan.listviewupdate;


import android.os.Bundle;


import android.support.v7.app.AppCompatActivity;


import android.view.View;


import android.widget.AdapterView;


import android.widget.ListView;


import android.widget.TextView;


import java.util.ArrayList;


import java.util.List;


import cn.bluemobi.dylan.listviewupdate.adapter.CommonAdapter;


import cn.bluemobi.dylan.listviewupdate.adapter.CommonViewHolder;


public class MainActivity extends AppCompatActivity {


private ListView listView;


private List datas;


private CommonAdapter commonAdapter;


@Override


protected void onCreate(Bundle savedInstanceState) {


super.onCreate(savedInstanceState);


updateOneTest();


}


/**


  • 只是局部更新某个界面


*/


private void updateOneTest() {


setContentView(R.layout.activity_main);


listView = (ListView) findViewById(R.id.listview);


datas = new ArrayList<>();


for (int i = 0; i < 20; i++) {


datas.add("万能适配器测试" + i);


}


commonAdapter = new CommonAdapter(this, datas, R.layout.item) {


@Override


protected void convertView(View item, String s) {


TextView textView = CommonViewHolder.get(item, R.id.textView);


textView.setText(s);


}


};


listView.setAdapter(commonAdapter);


listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {


@Override


public void onItemClick(AdapterView parent, View view, int position, long id) {


datas.set(position, "update 万能适配器测试" + position);


updateSingle(position);


}


});


}


/**


  • 第一种方法 更新对应 view 的内容

  • @param position 要更新的位置


*/


private void updateSingle(int position) {


/第一个可见的位置/


int firstVisiblePosition = listView.getFirstVisiblePosition();


/最后一个可见的位置/


int lastVisiblePosition = listView.getLastVisiblePosition();


/在看见范围内才更新,不可见的滑动后自动会调用 getView 方法更新/


if (position >= firstVisiblePosition && position <= lastVisiblePosition) {


/获取指定位置 view 对象/


View view = listView.getChildAt(position - firstVisiblePosition);


TextView textView = (TextView) view.findViewById(R.id.textView);


textView.setText(datas.get(position));


}


}


}


2.ListView 实现局部刷新方法二: 调用一次 getView()方法


这种方法是调用适配器对应的 getView 方法,用它里面的代码对界面进行刷新。


package cn.bluemobi.dylan.listviewupdate;


import android.os.Bundle;


import android.support.v7.app.AppCompatActivity;


import android.view.View;


import android.widget.AdapterView;


import android.widget.ListView;


import android.widget.TextView;


import java.util.ArrayList;


import java.util.List;


import cn.bluemobi.dylan.listviewupdate.adapter.CommonAdapter;


import cn.bluemobi.dylan.listviewupdate.adapter.CommonViewHolder;


public class MainActivity extends AppCompatActivity {


private ListView listView;


private List datas;


private CommonAdapter commonAdapter;


@Override


protected void onCreate(Bundle savedInstanceState) {


super.onCreate(savedInstanceState);


updateOneTest();


}


/**


  • 只是局部更新某个界面


*/


private void updateOneTest() {


setContentView(R.layout.activity_main);


listView = (ListView) findViewById(R.id.listview);


datas = new ArrayList<>();


for (int i = 0; i < 20; i++) {


datas.add("万能适配器测试" + i);


}


commonAdapter = new CommonAdapter(this, datas, R.layout.item) {


@Override


protected void convertView(View item, String s) {


TextView textView = CommonViewHolder.get(item, R.id.textView);


textView.setText(s);


}


};


listView.setAdapter(commonAdapter);


listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {


@Override


public void onItemClick(AdapterView parent, View view, int position, long id) {


datas.set(position, "update 万能适配器测试" + position);


updateItem(position);


}


});


}


/**


  • 第二种方法 调用一次 getView()方法;

  • Google 推荐的做法

  • @param position 要更新的位置


*/


private void updateItem(int position) {


/第一个可见的位置/


int firstVisiblePosition = listView.getFirstVisiblePosition();


/最后一个可见的位置/


int lastVisiblePosition = listView.getLastVisiblePosition();


/在看见范围内才更新,不可见的滑动后自动会调用 getView 方法更新/


if (position >= firstVisiblePosition && position <= lastVisiblePosition) {


/获取指定位置 view 对象/


View view = listView.getChildAt(position - firstVisiblePosition);


commonAdapter.getView(position, view, listView);


}


}


}


最后封装在万能适配器当中


package cn.bluemobi.dylan.listviewupdate.adapter;


import android.content.Context;


import android.util.Log;


import android.view.LayoutInflater;


import android.view.View;


import android.view.ViewGroup;


import android.widget.BaseAdapter;


import android.widget.ListView;


import java.util.List;


/**


  • Created by yuandl on 2016-10-13.

  • 万能适配器


*/


public abstract class CommonAdapter extends BaseAdapter {


private Context context;


private List datas;


private int layoutId;


public CommonAdapter(Context context, List datas, int layoutId) {


this.context = context;


this.datas = datas;


this.layoutId = layoutId;


}


@Override


public int getCount()


《Android 学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享


{


return datas == null ? 0 : datas.size();


}


@Override


public T getItem(int position) {


return datas.get(position);


}


@Override


public long getItemId(int position) {


return position;


}


@Override


public View getView(int position, View convertView, ViewGroup parent) {


if (convertView == null) {


convertView = LayoutInflater.from(context).inflate(layoutId, null);


}


Log.d("listview", "---------getView()-----------");


T t = getItem(position);


convertView(convertView, t);


return convertView;


}


/**


  • 局部更新数据,调用一次 getView()方法;Google 推荐的做法

  • @param listView 要更新的 listview

  • @param position 要更新的位置


*/


public void notifyDataSetChanged(ListView listView, int position) {


/第一个可见的位置/


int firstVisiblePosition = listView.getFirstVisiblePosition();


/最后一个可见的位置/


int lastVisiblePosition = listView.getLastVisiblePosition();


/在看见范围内才更新,不可见的滑动后自动会调用 getView 方法更新/


if (position >= firstVisiblePosition && position <= lastVisiblePosition) {


/获取指定位置 view 对象/


View view = listView.getChildAt(position - firstVisiblePosition);


getView(position, view, listView);


}


}


/**


  • 需要去实现的对 item 中的 view 的设置操作

  • @param item

  • @param t


*/


protected abstract void convertView(View item, T t);


}


我们每次更新的时候只需要调用 notifyDataSetChanged(ListView listView, int position),传入对应的要更新的 listview 和要更新的位置 position 即可


三 ListView 实现 Item 单选 多选效果


首先,在 ListView 的布局中设置了 android:choiceMode 属性后,item 布局需要实现 checkable,才有选中效果。


checkable 接口:


/**


  • Defines an extension for views that make them checkable.


*/


public interface Checkable {


/**


  • 设置是否选中。

  • 当我们点击 item 的时候,

  • 会调用这个方法。


*/


void setChecked(boolean checked);


/**


*判断是否选中


*/


boolean isChecked();


/**


  • 如果当前是选中的状态,

  • 调用该方法后取消选中,

  • 反之,选中


*/


void toggle();


}


实现单选效果:


1、 ListView 布局中 android:choiceMode 设置为 singleChoice。


2、选取实现了 checkable 接口的 View 或者 ViewGroup 作为 item 布局控件。


当 item 展示的数据比较简单,例如就是一段文本,item 布局可以直接使用系统自带的 CheckedTextView 控件,该控件有一个属性:android:checkMark=”?android:listChoiceIndicatorSingle”为单选样式;“?android:listChoiceIndicatorMultiple”为多选样式。若要修改显示的样式,可以自己写一个 selector,然后 checkMark 指定为这个 selector。例如:


在 drawable 文件夹下面创建一个 ic_hideable_item.xml 文件


<selector xmlns:android="http://schemas.android.com/apk/res/android">


<item android:state_checked="false" android:drawable="@mipmap/ic_hideable_item_unchecked" />


<item android:drawable="@mipmap/ic_hideable_item_checked" />


</selector>


checkMark 指定为上面的那个 xml 文件:


<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"


android:id="@+id/tv_single_choice"


android:layout_width="match_parent"


android:layout_height="?android:attr/listPreferredItemHeightSmall"


android:textSize="14sp"


android:gravity="center_vertical"


android:checkMark="@drawable/ic_hideable_item"


android:paddingLeft="16dp"


android:paddingRight="16dp">


</CheckedTextView>


实现多选效果:


1、 ListView 布局中 android:choiceMode 设置为 multipleChoice。


2、选取实现了 checkable 接口的 View 或者 ViewGroup 作为 item 布局控件。


这里笔者自定义一个控件实现 Checkable 接口。代码如下:


public class CheckableLayout extends RelativeLayout implements Checkable {


private static final int[] CHECKED_STATE_SET = {android.R.attr.state_checked};


private boolean mChecked;


public CheckableLayout(Context context, AttributeSet attrs) {


super(context, attrs);


}


@Override


public void setChecked(boolean b) {


if (b != mChecked){


mChecked = b;


refreshDrawableState();


}


}


@Override


public boolean isChecked() {


return mChecked;


}


@Override


public void toggle() {


setChecked(!mChecked);


}


@Override


protected int[] onCreateDrawableState(int extraSpace) {


final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);


if (isChecked()) mergeDrawableStates(drawableState, CHECKED_STATE_SET);


return drawableState;


}


}


应用到 item 布局:


<com.jm.customchoicelist.CheckableLayout xmlns:android="http://schemas.android.com/apk/res/android"


xmlns:tools="http://schemas.android.com/tools"


android:layout_width="match_parent"


android:layout_height="wrap_content"


android:orientation="horizontal">


<TextView


android:id="@+id/tv_content"


android:layout_width="wrap_content"


android:layout_height="wrap_content"


android:duplicateParentState="true"

总结

Android 架构学习进阶是一条漫长而艰苦的道路,不能靠一时激情,更不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。所以:贵在坚持!


上面分享的字节跳动公司 2021 年的面试真题解析大全,笔者还把一线互联网企业主流面试技术要点整理成了视频和 PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。



【Android 高级架构视频学习资源】


Android 部分精讲视频领取学习后更加是如虎添翼!进军 BATJ 大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务 Curd 而已!现如今市场上初级程序员泛滥,这套教程针对 Android 开发工程师 1-6 年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶 Android 中高级、架构师对你更是如鱼得水,赶快领取吧!


本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

用户头像

嘟嘟侠客

关注

还未添加个人签名 2021.03.19 加入

还未添加个人简介

评论

发布
暂无评论
Android关于 ListView知识点,Android面试题集锦