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

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

  •  
  •   Features · 2021-11-24 17:20:25 +08:00 · 7248 次点击
    这是一个创建于 936 天前的主题,其中的信息可能已经有所发展或是发生改变。

    编译通过,但是会闪退


    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 条附言  ·  2021-11-24 18:08:33 +08:00

    这样写就完全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 条附言  ·  2021-11-24 18:12:27 +08:00
    Logcat 报错:
    java.lang.NullPointerException: Attempt to read from field 'android.widget.ImageView cn.mousover.helloworld4.MyGridAdapter$ViewHolder.img' on a null object reference
    第 3 条附言  ·  2021-11-24 18:21:14 +08:00

    前面使用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  
       2021-11-24 17:28:29 +08:00
    虽然没做过 android 你这个 debug 一下不就是了
    holder, holder.img 是不是空,arr 或者 arr.get(i) 是不是空
    SupperMary
        2
    SupperMary  
       2021-11-24 17:30:13 +08:00   ❤️ 1
    adb shell 上去,logcat -b crash 会告诉你很详细的错误原因
    Features
        3
    Features  
    OP
       2021-11-24 17:30:20 +08:00
    @hello2090 这个确实空指针了,但是不知道什么原因导致的
    集合长度为 4 ,会更新 4 次,但是集合数据是正常的
    hello2090
        4
    hello2090  
       2021-11-24 17:34:06 +08:00   ❤️ 1
    @Features 很简单啊,arr 更新的时候打个 log, 运行 holder.img.setImageResource(arr.get(i).getRid()); 之前打个 log 看看呗

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

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

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

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

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

    Kotlin + Jetpack 一套框架

    Kotlin + jetpack Compose 新的声明式 UI

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

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

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