V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Features
V2EX  ›  Android

刚刚开始学习 Android,请问一下下面这两行代码为什么会导致闪退?

  •  
  •   Features · 13 天前 · 2578 次点击

    编译通过,但是会闪退


    public View getView(int i, View view, ViewGroup viewGroup) {
            ViewHolder holder;
            if(view == null){
                holder = new ViewHolder();
                mView = LayoutInflater.from(context).inflate(R.layout.grid_item,viewGroup,false);
                holder.img  = (ImageView) mView.findViewById(R.id.icon_item);
                holder.title = (TextView) mView.findViewById(R.id.icon_text);
            }else{
                holder = (ViewHolder) mView.getTag();
            }
    
            //这两行会导致闪退
            holder.img.setImageResource(arr.get(i).getRid());
            holder.title.setText(arr.get(i).getTitle());
    
            Log.e("myapp","abc");
    
            return mView;
        }
    
    第 1 条附言  ·  13 天前

    这样写就完全OK,应该是view.getTag() 没有正确返回ViewHolder对象

            mView = LayoutInflater.from(context).inflate(R.layout.grid_item,viewGroup,false);
            ImageView img  = (ImageView) mView.findViewById(R.id.icon_item);
            TextView title = (TextView) mView.findViewById(R.id.icon_text);
    
            img.setImageResource(arr.get(i).getRid());
            title.setText(arr.get(i).getTitle());
    
            return mView;
    
    第 2 条附言  ·  13 天前
    Logcat 报错:
    java.lang.NullPointerException: Attempt to read from field 'android.widget.ImageView cn.mousover.helloworld4.MyGridAdapter$ViewHolder.img' on a null object reference
    第 3 条附言  ·  13 天前

    前面使用ListView,没有setTag,却能正常跑起来,所以我忽略了setTag这个api

                ViewHolder holder = null;
                if(view == null){
                    holder = new ViewHolder();
                    mView = LayoutInflater.from(context).inflate(R.layout.view_item,viewGroup,false);
                    holder.title =  (TextView) mView.findViewById(R.id.title);
                    holder.desc = (TextView) mView.findViewById(R.id.desc);
                    holder.img = (ImageView) mView.findViewById(R.id.img);
                }else{
                    holder =(ViewHolder)mView.getTag();
                }
    
                holder.title.setText(data.get(i).getTitle());
                holder.desc.setText(data.get(i).getDesc());
                holder.img.setImageResource(data.get(i).getIcon());
    
                return mView;
    
    
    32 条回复    2021-12-07 14:10:00 +08:00
    hello2090
        1
    hello2090  
       13 天前
    虽然没做过 android 你这个 debug 一下不就是了
    holder, holder.img 是不是空,arr 或者 arr.get(i) 是不是空
    SupperMary
        2
    SupperMary  
       13 天前   ❤️ 1
    adb shell 上去,logcat -b crash 会告诉你很详细的错误原因
    Features
        3
    Features  
    OP
       13 天前
    @hello2090 这个确实空指针了,但是不知道什么原因导致的
    集合长度为 4 ,会更新 4 次,但是集合数据是正常的
    hello2090
        4
    hello2090  
       13 天前   ❤️ 1
    @Features 很简单啊,arr 更新的时候打个 log, 运行 holder.img.setImageResource(arr.get(i).getRid()); 之前打个 log 看看呗

    你这个只是读,而且还不是数值不对,而是直接 null, 应该不会是多线程的问题,
    lvdb
        5
    lvdb  
       13 天前 via Android   ❤️ 1
    if 分支结尾需要 mView.setTag(holder)一下吧?现在安卓基本上不用 listview 了,基本上都是 recyclerview 来处理了。可以直接学 recyclerview
    xFrye
        6
    xFrye  
       13 天前   ❤️ 1
    ListView? 有想过通过 getTag 获取到的 holder 是从哪里来的么? viewHolder 不存下来的话,怎么会拿得到呢
    lvdb
        7
    lvdb  
       13 天前 via Android
    @xFrye 哈哈初学者,可能还不是太明白这个 item 复用吧
    xFrye
        8
    xFrye  
       13 天前
    @lvdb 应该是的,不过写的时候还是要多思考一下。

    https://juejin.cn/post/6844903911225032712 楼主可以看看这个梳理下,不过现在基本上确实 recyclerview 用的比较多了
    busymilk
        9
    busymilk  
       13 天前 via iPhone
    你没有 setTag. getTag 当然是空
    xuhaoyangx
        10
    xuhaoyangx  
       13 天前
    现在就别用 listview 了
    Features
        11
    Features  
    OP
       13 天前
    @xFrye 是 GridView,ListView 写了就没问题😂
    Features
        12
    Features  
    OP
       13 天前
    @xuhaoyangx 只是当预热了解
    sankemao
        13
    sankemao  
       13 天前
    没有 setTag,当然 get 不到,而且下面你的写法,失去了复用机制
    youxiachai
        14
    youxiachai  
       13 天前
    这代码...不是我 10 年前的写法吗....

    现在用 RV 用不着这样写了啊...
    youxiachai
        15
    youxiachai  
       13 天前
    不对...按道理,现在基本 RV 一把梭.... lz 用的什么入门资料..怎么还有这么远古的用法
    Features
        16
    Features  
    OP
       13 天前
    @xFrye 确实是要先 setTag ,但是我之前写了一个 demo ,是 ListView 的,没有 setTag 却可以😭
    Features
        17
    Features  
    OP
       13 天前
    @lvdb 是的是的,谢谢
    Features
        18
    Features  
    OP
       13 天前
    @youxiachai 就是菜鸟教程,哈哈,没事,反正先了解下,应该都没问题吧
    Features
        19
    Features  
    OP
       13 天前
    @sankemao 好奇怪欸,我用 ListView 的时候,不用 setTag 也能跑起来,用 GridView 的时候却报错了
    youxiachai
        20
    youxiachai  
       13 天前
    @Features 现在有 google 的 codelab 那么好的教程....完全搞不懂现在的年轻人,怎么去看采集网站的教程..
    Features
        21
    Features  
    OP
       13 天前
    @youxiachai 我是找了个视频,看了视频以后,做完视频的练习
    再自己找一些练习做的,纯看教程我有点吃力,学不动的感觉
    等我学完基础,肯定会去官网做一遍,巩固下
    可能这就是学渣吧😂
    学新知识都要学几回才能掌握
    youxiachai
        22
    youxiachai  
       13 天前
    @Features google 官方有专门针对新手的视频... 完整的一套最新,没必要看这种过时的资料
    a4390509
        23
    a4390509  
       13 天前   ❤️ 1
    不崩溃是因为数据少,item 没有填充满一个屏幕,所以 view 没有复用,所以逻辑走到了 view==null 的逻辑分支里面。

    崩溃是因为 view 复用了,但是你没有在 view 创建的时候 setTag ,所以在 else 逻辑分支里面获取的时候 getTag 是个空的
    ykrank
        24
    ykrank  
       13 天前   ❤️ 2
    八年老 Android ,从 Android2.0 适配起,建议你不要学客户端了。历史知识太多,真要靠这个吃饭,现在既要精通 Android ,又要精通 JVM ,各种常用的第三方框架源码都得看。最新代码基本都是 kotlin 。google 官方的推荐框架换了一茬又一茬,每次学习都是新架构。但是你要维护的工程完全可能有各种历史代码,不知道历史原因的话看起来就是乱麻。
    当然如果是自己写给自己玩的,那随意了,直接最新架构一把梭,完全不用在乎历史框架。不过这种情况下那也不如 google 新的 flutter ,还可以直接打包成 IOS 和 PC 端。
    windyskr
        25
    windyskr  
       13 天前 via Android
    @ykrank 真心请教现在学 Flutter 需要啥储备知识,去哪学习比较好?
    caixiangyu17
        26
    caixiangyu17  
       13 天前   ❤️ 1
    现在学安卓直接从 kotlin 和 jetpack compose 入门吧,没有安卓面试会不问你 kotlin coroutine 的,所以别写 java 了
    Features
        27
    Features  
    OP
       13 天前
    @ykrank 我有 java se 和 ee 基础,所以感觉用 java 轻松点
    kotlin 以后作为拓展再学习吧
    xuhaoyangx
        28
    xuhaoyangx  
       13 天前
    你真的要学 Android

    直接用最新的谷歌 jetpack 的东西

    Kotlin + Jetpack 一套框架

    Kotlin + jetpack Compose 新的声明式 UI

    flutter 也可以看看,flutter 和 compose 基本是一种思想,会一个另一个基本也差不多了。

    跨平台的可以学,但别以为能解万难,凡是涉及多一点点稍微底层一点的功能、API ,都要你懂原生。

    我现在做 SDK 的,遇到太多来自别的端转移动端,只会 RN Flutter weex Uniapp 等这些,水的不行。
    xuhaoyangx
        29
    xuhaoyangx  
       13 天前
    @Features 先学 kotlin
    olindays
        30
    olindays  
       12 天前
    用《第一行代码》第三版,学习 Android 开发的同时也学了 kotlin ,我个人觉得这本书对我这种菜鸟水平的编程爱好者很友好,你不妨试试看。
    stardust21
        31
    stardust21  
       12 天前
    @ykrank 老哥中肯。
    @Features 列表直接学 RV 吧,看官方文档就行: https://developer.android.google.cn/guide/topics/ui/layout/recyclerview
    kujio
        32
    kujio  
       1 天前
    你这 holder 写的,holder 不是这么存的,也不是这么取的!
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3850 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 07:21 · PVG 15:21 · LAX 23:21 · JFK 02:21
    ♥ Do have faith in what you're doing.