Android ListView 相关问题(面试常用)

今日,看到群里朋友发的一部分面试题,决定把这这些面试题的答案写下来,如下:

1、ListView怎么和ScrollView兼容? ok
2、ViewPager无限轮播图片
3、out of memory内存溢出怎么解决
4、三级缓存如何实现
5、登录时怎么保存用户名密码实现下次自动登录
6、如果sp只存储用户名,比如三个用户都存在sp里,取出来怎么取?存进去怎么存?你怎么区分
7、你们登录就只有登录成功和登录失败吗?难道没有重连机制?断网了以后又有网了重新来到登录界面怎么登录?
8、怎么保持在线状态
9、toobar,actionbar玩的转不?
10、include标签总会吧?
11、webview配置会吧
12、CoordinatorLayout和recycleview会吧
13、tab用actionbar就能实现你知道吗?
14、你知道Listview里有Button就点不动了你知道吗 ok
15、简单的动画你会吗?哪怕是运用到activity的出现与退出
16、view的点击事件跟dialog的点击事件很容易引错包
17、集合List<>为什么动态增长?它有默认长度的,有时候用他步入指定好长度的数组
18、下载时,异步任务和子线程他俩的区别
19、recycleview代替listview,gridview,瀑布流三种模式切换自如
20、listview怎么优化 ok
21、fragment的俩个适配器的区别
22、MVC,MVP
23、注解?findviewbyid
24、socket,http,xmpp,rstp这些协议
25、oom内存泄漏

今天决定先写ListView相关的,我把上述的1、14、20放到一起来说,也就是本篇文章,其他的稍后有时间持续更新,大家如果对此感兴趣的话,请关注我,我们一起学习。

================================================

ListView怎么和ScrollView兼容?

我们知道,有些时候我们需要在ListView外层嵌套一层ScrollView,代码如下:

    <ScrollView
        android:id="@+id/scrollview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <ListView
            android:id="@+id/listview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"></ListView>
    </ScrollView>

只要稍微有点经验的人都知道这是会出现什么问题,没错,就是“Listview不能显示正常的条目,只显示一条或二条”,这是怎么回事呢?这是因为:由于listView在scrollView中无法正确计算它的大小, 故只显示一行。
当目前为止,我知道的针对这一问题的解决办法有:

1. 方法一:重写ListView, 覆盖onMeasure()方法
activity_list_view_scroll_view_test.xml:
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.art.demo.ListViewScrollViewTestActivity">
    <ScrollView
        android:id="@+id/scrollview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <com.art.demo.WrapperListView
            android:id="@+id/listview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </ScrollView>
</merge>

WrapperListView.java:
public class WrapperListView extends ListView {
    public WrapperListView(Context context) {
        super(context);
    }
    public WrapperListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public WrapperListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    public WrapperListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }
    /**
     * 重写该方法,达到使ListView适应ScrollView的效果
     */
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
    }
}

ListViewScrollViewTestActivity.java:
public class ListViewScrollViewTestActivity extends AppCompatActivity {

    private ScrollView scrollView;
    private WrapperListView listView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list_view_scroll_view_test);
        scrollView = (ScrollView) findViewById(R.id.scrollView);
        listView = (WrapperListView) findViewById(R.id.listview);
        initListVeiw();
    }

    private void initListVeiw() {
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            list.add("第 " + i + " 条");
        }
        listView.setAdapter(new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, list));
    }
}

另外,哪位大神可以告诉我在代码块(```)中,怎么给某一行加粗,或者做一些其他明显标记??????????????
2. 方法二:动态设置listview的高度,不需要重写ListView

只需要在setAdapter之后调用如下方法即可:

public void setListViewHeightBasedOnChildren(ListView listView) {
        // 获取ListView对应的Adapter
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null) {
            return;
        }
        int totalHeight = 0;
        for (int i = 0, len = listAdapter.getCount(); i < len; i++) {
            // listAdapter.getCount()返回数据项的数目
            View listItem = listAdapter.getView(i, null, listView);
            // 计算子项View 的宽高
            listItem.measure(0, 0);
            // 统计所有子项的总高度
            totalHeight += listItem.getMeasuredHeight();
        }
        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        // listView.getDividerHeight()获取子项间分隔符占用的高度
        // params.height最后得到整个ListView完整显示需要的高度
        listView.setLayoutParams(params);
    }

另外,这时,这时最好给ListView之外嵌套一层LinearLayout,不然有时候这种方法会失效,如下:

<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.art.demo.ListViewScrollViewTestActivity">
    <ScrollView
        android:id="@+id/scrollview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ListView
                android:id="@+id/listview"
                android:layout_width="fill_parent"
                android:layout_height="match_parent"
                android:background="#FFF4F4F4"
                android:dividerHeight="0.0dip"
                android:fadingEdge="vertical" />
        </LinearLayout>
    </ScrollView>
</merge>
3. 方法三:在xml文件中,直接将Listview的高度写死

可以确定的是:这种方式可以改变ListView的高度,但是,还有一个严重的问题就是listview的数据是可变动的,除非你能正确的写出listview的高度,否则这种方式就是个鸡肋。
如下:

<ScrollView
        android:id="@+id/scrollview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <ListView
                android:id="@+id/listview"
                android:layout_width="fill_parent"
                android:layout_height="300dip"
                android:background="#FFF4F4F4"
                android:dividerHeight="0.0dip"
                android:fadingEdge="vertical" />
        </LinearLayout>
    </ScrollView>
4. 方法四:

某些情况下,其实我们可以完全避免ScrollView嵌套Listview,比如使用listview的addHeader() 函数来实现预期效果或者利用布局的特性达到预期效果,当然,具体怎么用,只有在开发中慢慢琢磨,慢慢总结了.

至此,关于“ListView怎么和ScrollView兼容”这个问题就算是回答完了,如果有不明白的地方可以问我,同样,那里有错误也欢迎大家指出,真的不胜感激。

接下来要说的就是!!!!!

listview怎么优化?

关于Listview的优化,只要面试过的人,我相信都对这个题很熟悉,不管有没有人问过你这个题,我想你自己也一定准备过,否则,嘿嘿!!!!!而且网上也一搜一大把这里就简单提几个主要的:
1)、convertView复用,对convetView进行判空,当convertView不为空时重复使用,为空则初始化,从而减少了很多不必要的View的创建
2)定义一个ViewHolder,封装Listview Item条目中所有的组件,将convetView的tag设置为ViewHolder,不为空时通过ViewHolder的属性获取对应组件即可
3)、当ListView加载数据量较大时可以采用分页加载和图片异步加载(关于Listview分页加载和图片异步加载思路请看接下来的文章内容)

下面就是关于Listview的一些相关拓展

1. 打开套有 ListVew的 ScrollView的页面布局 默认 起始位置不是最顶部?

解决办法有两种:
方法一:把套在里面的ListVew 不让获取焦点即可。listview.setFocusable(false);注意:在xml布局里面设置android:focusable=“false”不生效
方法二:myScrollView.smoothScrollTo(0,0);

2. 上拉加载和下拉刷新怎么实现?

实现OnScrollListener 接口重写onScrollStateChanged 和onScroll方法,
使用onscroll方法实现”滑动“后处理检查是否还有新的记录,如果有,调用 addFooterView,添加记录到adapter, adapter调notifyDataSetChanged 更新数据;如果没有记录了,把自定义的mFooterView去掉。使用onScrollStateChanged可以检测是否滚到最后一行且停止滚动然后执行加载

3. listview失去焦点怎么处理?

在listview子布局里面写,可以解决焦点失去的问题
android:descendantFocusability=”blocksDescendants”

4. ListView图片异步加载实现思路?

1.先从内存缓存中获取图片显示(内存缓冲)
2.获取不到的话从SD卡里获取(SD卡缓冲,,从SD卡获取图片是放在子线程里执行的,否则快速滑屏的话会不够流畅)
3.都获取不到的话从网络下载图片并保存到SD卡同时加入内存并显示(视情况看是否要显示)

5. 你知道Listview里有Button就点不动了你知道吗?

原因是button强制获取了item的焦点,只要设置button的focusable为false即可。

6. 如何自定义一个Adapter(有兴趣的可以看一下,大家不呀扔我鸡蛋)

继承自BaseAdapter实现里面的方法,listView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到listView的长度,然后根据这个长度,调用getView()逐一绘制每一行。如果你的getCount()返回值是0的话,列表将不显示同样return 1,就只显示一行。系统显示列表时,首先实例化一个适配器(这里将实例化自定义的适配器)。当手动完成适配时,必 须手动映射数据,这需要重写getView()方法。系统在绘制列表的每一行的时候将调用此方法。getView()有三个参数,position表示将显示的是第几行,covertView是从布局文件中inflate来的 布局。我们用LayoutInflater的方法将定义好的main.xml文件提取成View实例用来显示。
然后 将xml文件中的各个组件实例化(简单的findViewById()方法)。这样便可以将数据对应到各个组件上了。但是按钮为了响应点击事件,需要为它添加点击监听器,这样就能捕获点击事件。至此一个自定 义的listView就完成了,现在让我们回过头从新审视这个过程。系统要绘制ListView了,
他首先获得 要绘制的这个列表的长度,然后开始绘制第一行,怎么绘制呢?
调用getView()函数。在这个函数里面 首先获得一个View(实际上是一个ViewGroup),然后再实例并设置各个组件,显示之。好了,绘制完这一行了。那 再绘制下一行,直到绘完为止。在实际的运行过程中会发现listView的每一行没有焦点了,这是因为Button抢夺了listView的焦点,只要布局文件中将Button设置为没有焦点就OK了。

7. listview分页加载的步骤?

通常实现分页加载有两种方式,一种是在ListView底部设置一个按钮,用户点击即加载。另一种是当用户滑动到底部时自动加载。
在ListView底部设置一个按钮,用户点击即加载实现思路:

        // 加上底部View,注意要放在setAdapter方法前
        ListView.addFooterView(moreView);
        bt.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                pg.setVisibility(View.VISIBLE);// 将进度条可见
                bt.setVisibility(View.GONE);// 按钮不可见
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        loadMoreDate();// 加载更多数据
                        bt.setVisibility(View.VISIBLE);
                        pg.setVisibility(View.GONE);
                        mSimpleAdapter.notifyDataSetChanged();// 通知listView刷新数据
                    }
                }, 2000);
            }
        });

当用户滑动到底部时自动加载实现思路:
实现OnScrollListener 接口重写onScrollStateChanged 和onScroll方法,使用onscroll方法实现”滑动“后处理检查是否还有新的记录,如果有,添加记录到adapter, adapter调用 notifyDataSetChanged 更新数据;如果没有记录了,则不再加载数据。使用onScrollStateChanged可以检测是否滚到最后一行且停止滚动然后执行加载.

8. ViewHolder内部类非得要声明成static的呢?

这不是Android的优化,而是Java提倡的优化,
如果声明成员类不要求访问外围实例,就要始终把static修饰符放在它的声明中,使它成为静态成员类,而不是非静态成员类。
因为非静态成员类的实例会包含一个额外的指向外围对象的引用,保存这份引用要消耗时间和空间,并且导致外围类实例符合垃圾回收时仍然被保留。如果没有外围实例的情况下,也需要分配实例,就不能使用非静态成员类,因为非静态成员类的实例必须要有一个外围实例。

9. Listview每个item有特效进入视图
10. ScrollView、ListView剖析 - 上下拉伸回弹阻尼效果
11. 自定义控件-下拉刷新和上拉加载的listView

================================================

前边还有几篇关于面试的文章,有兴趣的小伙伴可以去我的专题里溜达溜达,另外我所有的简书文章目录在这里

更多内容请关注 我的专题
转载请注明 原文链接:
http://www.jianshu.com/p/b7741023bc6f

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值