【Fragment精深系列5】fragment findViewById()返回null完全解析

一、引入

??你是不是经常遇到在fragment中调用findViewById方法寻找fragment布局文件中的控件返回null的现象。我之前也遇到了这个问题,虽然后来解决了,但是心中一直有疑惑,最近有时间停下来,结合别人的解答和自己的思考,对这个问题进行彻底的梳理。

二、使用getActivity().findViewById

1、getActivity的介绍

??Fragment中有一个getActivity()的方法。返回与Fragment关联的Activity对象(通过该对象可以查找activity中的控件们(findViewById()))。当fragment生命周期结束并销毁时,getActivity()返回的会是null。onAttach和onDetach之间的其他生命周期方法都可以调用getActivity方法。

2、在Fragment的oncreateview()方法中使用

1)代码:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        //从数据库中得到黑名单的集合
        super.onActivityCreated(savedInstanceState);
        View view = inflater.inflate(R.layout.fragment_dark, container, false);
        infoList = DbManager.getInstance().getDarkList();
        listView = (ListView) getActivity().findViewById(R.id.dark);
        adapter = new DarkAdapter(getActivity(), infoList);
        listView.setAdapter(adapter);
        registerForContextMenu(listView);
        return view;
    }

2)结果:

空指针异常

3)分析:

??因为onCreateView时,fragment已经和activity绑定了,所以说getActivity是有值的,但是我们返回值为空,说明在activity的子控件中找不到fragment的控件——>说明fragment的控件还没有加到activity中。

??为什么呢?原因如下:

View view = inflater.inflate(R.layout.fragment_dark, container, false);

??该方法的第二个参数的意思是:root Optional view to be the parent of the generated hierarchy (if attachToRoot is true), or else simply an object that provides a set of LayoutParams values for root of the returned hierarchy (if attachToRoot is false.)

??该方法的第三个参数的意思是:Whether the inflated hierarchy should be attached to the root parameter? If false, root is only used to create the correct subclass of LayoutParams for the root view in the XML.

??在本代码中第三个参数为false,说明当前fragment的布局文件并没有被加到activity的布局中,所以你当然无法在activity中找到fragment的组件了。但是一旦onCreateView执行完了,系统就把fragment的布局文件加入到activity的布局文件中了。所以只要在onCreateView方法之后,我们通过getActivity().findViewById都是可以得到fragment的子控件的。所以下面的3结果就是对的。

??有的人可能有疑问了:如果我们把false改为true,这样是不是就可以在onCreateView使用getActivity().findViewById找到fragment的子控件了。事实上,这样做会产生异常,你把fragment的布局文件加到activity的布局一次,但是当onCreateView方法执行完之后,返回View,系统又执行了一次把fragment的布局文件加到activity的布局,就会产生错误。

3、在Fragment的onstart()方法中使用

1)代码:

    @Override
    public void onStart() {
        super.onStart();
        infoList = DbManager.getInstance().getDarkList();
        listView = (ListView) getActivity().findViewById(R.id.dark);
        adapter = new DarkAdapter(getActivity(), infoList);
        listView.setAdapter(adapter);
        registerForContextMenu(listView);
    }

2)结果:

正常

3)分析:

理解了2的分析,这里就没有问题了。

三、使用getview().findViewById

1、getview的介绍

开发文档的解释:

Get the root view for the fragment’s layout (the one returned by onCreateView(LayoutInflater, ViewGroup, Bundle)), if provided.

Returns

The fragment’s root view, or null if it has no layout.

2、在Fragment的oncreateview()方法中使用

1)代码:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        //从数据库中得到黑名单的集合
        super.onActivityCreated(savedInstanceState);
        View view = inflater.inflate(R.layout.fragment_dark, container, false);
        infoList = DbManager.getInstance().getDarkList();
        listView = (ListView) getView().findViewById(R.id.dark);
        adapter = new DarkAdapter(getActivity(), infoList);
        listView.setAdapter(adapter);
        registerForContextMenu(listView);
        return view;
    }

2)效果:

空指针异常

3)分析:

??我们看getView的方法解释:Get the root view for the fragment’s layout (the one returned by onCreateView(LayoutInflater, ViewGroup, Bundle)), if provided.而现在,我们在onCreateView内部使用getView,onCreateView还没有执行完,getView自然无法得到onCreateView的返回值。因此产生空指针异常

3、在Fragment的onstart()方法中使用

1)代码:

    @Override
    public void onStart() {
        super.onStart();
        infoList = DbManager.getInstance().getDarkList();
        listView = (ListView) getView().findViewById(R.id.dark);
        adapter = new DarkAdapter(getActivity(), infoList);
        listView.setAdapter(adapter);
        registerForContextMenu(listView);
    }

2)结果:

空指针异常

3)分析:

易理解

四、推荐的方式

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        //从数据库中得到黑名单的集合
        super.onActivityCreated(savedInstanceState);
        View view = inflater.inflate(R.layout.fragment_dark, container, false);
        infoList = DbManager.getInstance().getDarkList();
        listView = (ListView) view.findViewById(R.id.dark);
        adapter = new DarkAdapter(getActivity(), infoList);
        listView.setAdapter(adapter);
        registerForContextMenu(listView);
        return view;
    }

五、更多知识的讲解

1、findViewById

??findViewById()是View对象的方法,先通过inflate()方法得到View,调用这个View对象的getViewById()方法,就能得到这个View树上的子View。

??findViewById的完整写法是View.findViewById(),而不指定View时默认的是Context,因此当findViewById不是在context里执行时,要指定对应的View

例如:

userDialog=new Dialog(addevent.this);
userDialog.setContentView(R.layout.user_list);
userDialog.setTitle("请选择");
ListView lv=(ListView)userDialog.findViewById(R.id.userList);
lv.setAdapter(new MyAdapter());
userDialog.show();

??如上,实例化lv时必须指定userDialog.findViewById()而不能直接findViewById(),否则就会从Activity而不是Dialog的布局文件中找R.id.userList,此时当然会返回null,执行lv.setAdapter(new MyAdapter());时就会出现NullPointException异常。

??findViewById返回为null,原因是:find的View下面,没有包含对应的想要找的view,从而导致找不到,返回null。

??常见的findViewById返回null的问题:在setContentView调用之前,调用了findViewById去找main布局中的界面元素lv_contactbook,那么所得到的lv一定是null。正确的做法是将上面代码中加粗的哪一行,挪至setContentView方法调用之后。

2、inflate方法与 findViewById 方法区别

inflate方法与 findViewById 方法区别 | LayoutInflater的inflate函数用法详解 :http://www.cnblogs.com/loyea/archive/2013/04/27/3047248.html

inflate()和findViewById()函数的用法:http://blog.csdn.net/tanjunjie621/article/details/7334503

时间: 2024-10-19 13:03:36

【Fragment精深系列5】fragment findViewById()返回null完全解析的相关文章

findViewById返回null

Q:findViewById返回null? A: 代码逻辑错误: 最终,发现错误竟然是在layout文件中把android:id写成了android:name. android:name="@+id/button" 这个也能生成R.id.button,这个得留意了. 经验:字符串 "@+id/xxx" 格式即生成R.id.xxx,不论出现在哪里都行.

【Fragment精深系列9】Fragment vs Activity

1.fragment对于自身事件的处理,有的时候需要借助activity,使用接口回调. 2.fragment的生命周期受activity的影响. 3.findviewbyid的方式不同. 4.fragment的回退栈中存的是事务,而activity的任务栈中存的是activity对象.fragment的回退栈的管理由与他绑定的activity来负责管理,程序中必须显示的调用addToBackStack才会有效果. 5.activity是四大组件之一,而fragment不是.fragment的显

【Fragment精深系列7】Fragment切换优化

一.Fragment+RadioGroup ??在项目中需要进行Fragment的切换,一直都是用replace()方法来替换Fragment:然后总感觉切换的时候有些卡顿. 1.以前的代码: radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup radioGroup, int checkI

【Fragment精深系列8】Fragment对自身事件的处理

??Fragment自身的事件处理,不一定非要使用接口回调,在activity中实现具体的处理方法.如果事件处理比较简单,Fragment本身就可以处理,比如Fragment的上下文菜单的处理,简单的话,就不需要使用接口回调.下面就是一个简单的使用接口回调的案例: 一.案例:处理fragment中的popupmenu点击事件,跳转到其他的activity 二.fragment的代码: package com.ht.phoneguard.fragment; import android.app.A

android4.0中在onCreate方法中findViewById()返回null

问题描述 我用findViewById为什么取不到控件,我是android初学者,还请各位前辈指点 解决方案1 大侠,你自己不是写在了Fragment里面么.......你在onResume里面写应该可以了 解决方案2 你加载的布局是activity_main,所以activity_main.xml需要有对应的id,你在fragment_main里找没用的. 解决方案3 引用 2 楼 svenwang 的回复: 你加载的布局是activity_main,所以activity_main.xml需要

Android界面隐藏软键盘的探索(兼findViewById返回null解决办法)

最近写的APP,老师说我的登陆界面虽然有ScrollView滑动,但用户体验不太好,因为软键盘会挡住输入框或登录button(小米Pad,横屏,当指定只能输入数字时没找到关闭系统自带键盘的下箭头). 虽然我觉得ScrollView就够用了,能找到登录按钮…… 在默默吐槽了下连搜狗都有的功能小米没有后,上网上搜索了下解决办法. 首先,当activity加载完成后,屏蔽EditText自动弹出软键盘,需要一句话: 1 getWindow().setSoftInputMode(WindowManage

Android系列之Fragment(二)Fragment的生命周期和返回栈

Android系列之Fragment(二)Fragment的生命周期和返回栈 - Android - 次元立方网 - 电脑知识与技术互动交流平台 [正文] 上一章节中(Android系列之Fragment(一)----Fragment加载到Activity当中),我们对Fragment的生命周期进行了简单介绍,这一章节将对生命周期和返回栈进行详细介绍. 一.Fragment的生命周期初探: 因为Fragment必须嵌入在Acitivity中使用,所以Fragment的生命周期和它所在的Activ

Android系列之Fragment(二)----Fragment的生命周期和返回栈

?[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/3983234.html 联系方式:[email protected] [正文] 上一章节中(Android系列之Fragment(一)----Fragment加载到Activity当中),我们对Fragment的生命周期进行了简单介绍,这一章节将对生命周期和返回栈进行详细介绍. 一.Fragmen

Android系列之Fragment(一)----Fragment加载到Activity当中

Android系列之Fragment(一)----Fragment加载到Activity当中 ?[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/3978989.html 联系方式:[email protected] [正文] Android上的界面展示都是通过Activity实现的,Activity实在是太常用了.但是Activity也有它的局限性