zoukankan      html  css  js  c++  java
  • Android开发:getViewById返回null的原因定位

          近期在研究开发一些基于AndroidApp,遇到了一些问题。当中一个比較关键的是在Activity中的onCreate()方法中获取Button对象。代码大概例如以下:

     

    private Button mTrueButton;

    @Override

    public void onCreateBundle savedInstanceState{

       super.onCreate(savedInstanceState);

       setContentView(R.layout.activity_quiz);

     

       mTrueButton = (Button) getViewById(R.id.true_button);

       mTrueButton.setOnClickListener(…);

     

    }

     

    该代码是依据一本android的编程指南进行改动的,但意想不到的是。一运行,app提示系统错误,终止运行,通过debug跟踪发现:mTrueButtonnull,系统运行到mTrueButton.setOnclickListener抛出java.lang.NullPointerException非常明显,此时调用getViewById无法获取到Button这个View对象,于是開始网上搜索资料。觉得可能的原因是以下几个:

    一,调用顺序不当导致的异常

    持这样的观点的主要原因是getViewById的调用放到了setContentView之前。例如以下:

    super.onCreate(savedInstanceState);

    mTrueButton = ButtongetViewById(R.id.true_button);

    setContentView(R.layout.activity_quiz);

     

    理由是:当activity 调用 setContentView() 时,android 才会去绘制 layout 上的各个元素,并为其分配内存。

    仅仅有 分配了内存以后,才干继续运行 ,findViewById(); 才干得到引用,不然得到空引用,空引用意味着,后面使用对应变量时就会发生訪问的对象不存在的问题。

    并且当Activity又一次setContentView()以后,那些之前绘制的控件,内存都被灭掉了。

    所以,若是通过setContentView 来达到画面切换目的的。要注意又一次绘制以后又一次取得引用

     

     

    二。getViewById的上下文对象不匹配

    这样的方式让笔者想到Javascript中的document.getElementById,两者具有很高的相似性,getElementById的调用须要指定相应的document对象。表示从该document对象获取元素,同理,Android中的getViewById的完整调用是View.getViewById。因此须要关注该方法默认的context对象。通常是this,即当前的Activity。但有时候可能不是这样,如:

     

    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异常

     

    三。开发工具Eclipse导致的问题

    假定在自定的AdaptergetView方法中有类似例如以下的代码:

     

    View rowview = (View)inflater.inflate(R.layout.rowview, parent, false);

     

    TextView tv_contact_id =(TextView)rowview.findViewById(R.id.tv_contact_id);

     

    TextView tv_contactname =(TextView)rowview.findViewById(R.id.tv_contactname);

     

    有时候竟然也会发现rowview非空。但tv_contact_idtv_contactname都是null。细致看代码。怎么也看不出错误来。究竟是什么原因造成的呢?答案是Eclipse造成的。要解决问题。须要这个项目clean一次(Project菜单 -> Clean子菜单),这样就OK了。

     

     

    四。新版本号SDK不能在onCreate方法中调用了-笔者的问题原因在此。

    重要的环境交代:刚学Android。在官网下载的新版的ADT以及新版的SDK在新版的IDE(ADT)创建项目时假设你的最小版本号(minimumrequiredSDK)要支持4.0下面版,而且目标版本号为(4.0+),那么此时IDE会为你创建一个兼容包(appcompat_v7)创建项目后,这个时候在生成的项目主Activity不是曾经的那种继承的Activity,而是继承的ActionBarActivity

       此时,假设你仍然用旧的办法在onCreate调用getViewById,那么会返回null,原因是:在新的layout文件不是存放在默认的(res/layout/activity_quiz.xml)文件里,而是存放在(res/layout/fragment_quiz.xml)文件里。所以要在fragment_quiz.xml去找相应的ID才会找到,而新的IDE生成的代码中载入(fragment_quiz.xml)文件是在一个内部类载入的,所以一种方法是:我们能够在内部类载入处来得到Button

        /**

         * A placeholder fragment containing a simple view.

         */

        public static class PlaceholderFragment extends Fragment {

            

            View rootView = null;

            public PlaceholderFragment() {

            }

     

            @Override

            public View onCreateView(LayoutInflater inflater, ViewGroup container,

                    Bundle savedInstanceState) {

                rootView = inflater.inflate(R.layout.fragment_quiz, container, false);

                mTrueButton = (Button) rootView.findViewById(R.id.true_button);

              System.out.println(button);

                return rootView;

            }

          

        }

          第二种方法是:假设熟悉Activity的生命周期的人能够知道:onCreate调用的时候事实上还没构造相应的布局对象,因此不能在onCreate函数中获取控件。但能够在onStart函数中获取:(笔者的方案就是在onStart方法中获取的)

    @Override
    protected void onStart() {
       
      super.onStart();
       
      mTrueButton = (Button)findViewById(R.id.true_button);
       
      mTrueButton.setOnClickListener(new android.view.View.OnClickListener(){
           
      public void onClick(android.view.View v) {
           
          //TODO...
           
      }
       
      });
    }

     

     

     

  • 相关阅读:
    django migration
    Jenkins Jobs status dashboard by Build Monitor Plugin
    PyWebIO Write interactive web app in script way.
    Infrastructure as Code
    sqlalchemy
    reactsketch
    CI/CD System and gerrittrigger keypoints.
    mysql backup
    Alembic A database migrations tool for SQLAlchemy.
    docker support for inner loop
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/7142618.html
Copyright © 2011-2022 走看看