【问题标题】:Unable to start activity ComponentInfo NPE [duplicate]无法启动活动 ComponentInfo NPE [重复]
【发布时间】:2019-11-21 12:13:29
【问题描述】:

我正在尝试使用 Kotlin 和 Java 在 Android 上制作应用程序。

我的灵感来自这个教程:

https://www.youtube.com/watch?v=Qg3L_B9--zY

我稍微改了一下,现在出现了一个漂亮的错误:

“原因:java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()'”

这是错误日志:

11-21 10:46:03.006 27125-27125/? E/libprocessgroup: failed to make and chown /acct/uid_10058: Read- 
only file system
11-21 10:46:03.006 27125-27125/? W/Zygote: createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?

11-21 10:46:03.006 27125-27125/? I/art: Not late-enabling -Xcheck:jni (already on)
11-21 10:46:03.079 27125-27125/com.example.budgetapp I/System.out: Util Constructor
11-21 10:46:03.143 27125-27125/com.example.budgetapp E/MainActivity: before onCreate()
11-21 10:46:03.150 27125-27125/com.example.budgetapp W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter androidx.vectordrawable.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
11-21 10:46:03.183 27125-27125/com.example.budgetapp E/MainActivity: after onCreate()

11-21 10:46:03.206 27125-27125/com.example.budgetapp I/art: Rejecting re-init on previously-failed class java.lang.Class<androidx.core.view.ViewCompat$2>
11-21 10:46:03.206 27125-27125/com.example.budgetapp I/art: Rejecting re-init on previously-failed class java.lang.Class<androidx.core.view.ViewCompat$2>
11-21 10:46:03.275 27125-27125/com.example.budgetapp E/MainActivity: after setContentView()
11-21 10:46:03.275 27125-27125/com.example.budgetapp D/AndroidRuntime: Shutting down VM


    --------- beginning of crash
11-21 10:46:03.276 27125-27125/com.example.budgetapp E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.budgetapp, PID: 27125
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.budgetapp/com.example.budgetapp.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
        at android.app.ActivityThread.access$800(ActivityThread.java:151)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5254)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
        at android.content.ContextWrapper.getApplicationInfo(ContextWrapper.java:149)
        at android.view.ContextThemeWrapper.getTheme(ContextThemeWrapper.java:99)
        at android.content.Context.obtainStyledAttributes(Context.java:437)
        at androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor(AppCompatDelegateImpl.java:692)
        at androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor(AppCompatDelegateImpl.java:659)
        at androidx.appcompat.app.AppCompatDelegateImpl.findViewById(AppCompatDelegateImpl.java:479)
        at androidx.appcompat.app.AppCompatActivity.findViewById(AppCompatActivity.java:214)
        at Util.setupUIViews(Util.java:43)
        at com.example.budgetapp.MainActivity.onCreate(MainActivity.kt:27)
        at android.app.Activity.performCreate(Activity.java:5990)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387) 
        at android.app.ActivityThread.access$800(ActivityThread.java:151) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:135) 
        at android.app.ActivityThread.main(ActivityThread.java:5254) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at java.lang.reflect.Method.invoke(Method.java:372) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698) 

这是我的课程:

MainActivity.kt:

package com.example.budgetapp

import Util
import android.app.DatePickerDialog
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import java.util.*

class MainActivity : AppCompatActivity() {
    private val tag = "MainActivity"
    var util = Util()


    override fun onCreate(savedInstanceState: Bundle?) {
        Log.e(tag, "before onCreate()")

        super.onCreate(savedInstanceState)
        Log.e(tag, "after onCreate()")

        setContentView(R.layout.activity_main)
        Log.e(tag, "after setContentView()")



        util.setupUIViews()
        Log.e(tag, "after setupUIView()")

        util.initToolbar()
        Log.e(tag, "after initToolbar()")

        util.setupListView()
        Log.e(tag, "after setupListView()")



        //Calendars:
        val c = Calendar.getInstance()
        val year = c.get(Calendar.YEAR)
        val month = c.get(Calendar.MONTH)
        val day = c.get(Calendar.DAY_OF_MONTH)

        val c2 = Calendar.getInstance()
        val year2 = c2.get(Calendar.YEAR)
        val month2 = c2.get(Calendar.MONTH)
        val day2 = c2.get(Calendar.DAY_OF_MONTH)

        Log.e(tag, "year1: $year")
        Log.e(tag, "month1: $month")
        Log.e(tag, "month2: $month2")
        Log.e(tag, "day1: $day")

        //button click to show DatePickerDialog
        pickDateBtn.setOnClickListener {
            val dpd = DatePickerDialog(
                this,
                DatePickerDialog.OnDateSetListener {_, mYear, mMonth, mDay ->
                    var monthSel=mMonth+1
                    dateTv2.text = "$mDay/$monthSel/$mYear"
                },
                year,
                month,
                day
            )
            dpd.show()

            val dpd2 = DatePickerDialog(
                this,
                DatePickerDialog.OnDateSetListener {_, mYear2, mMonth2, mDay2 ->
                    var monthSel2=mMonth2+1
                    dateTv.text = "$mDay2/$monthSel2/$mYear2"
                },
                year2,
                month2,
                day2
            )
            dpd2.show()
        }
    }
}

SimpleAdapter.java:

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.budgetapp.R;

public class SimpleAdapter extends BaseAdapter {
    public Context mContext;
    private LayoutInflater layoutInflater;
    private TextView title, description;
    private String[] titleArray, descriptionArray;
    private ImageView imageView;


   public SimpleAdapter(Context context, String[] title, String [] description){
            mContext= context;
            titleArray=title;
            descriptionArray= description;
            layoutInflater= LayoutInflater.from(context);
        }



    @Override
    public int getCount(){
        return titleArray.length;
    }

    @Override
    public Object getItem(int position) {
        return  titleArray[position];
    }

    @Override
    public long getItemId(int position){
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if(convertView == null) {
            layoutInflater.inflate(R.layout.main_activity_single_item, null);
        }
        title= convertView.findViewById(R.id.tvMain);
        description = convertView.findViewById(R.id.tvDescription);
        imageView = convertView.findViewById(R.id.ivMain);

        title.setText(titleArray[position]);
        description.setText(descriptionArray[position]);

        if(titleArray[position].equalsIgnoreCase("Timetable")){
            imageView.setImageResource(R.drawable.timetable);
        }else if(titleArray[position].equalsIgnoreCase("Subjects")){
            imageView.setImageResource(R.drawable.book);
        }else if(titleArray[position].equalsIgnoreCase("Faculty")) {
            imageView.setImageResource(R.drawable.play);
        }else{
             imageView.setImageResource(R.drawable.settings);
            }
    return convertView;
    }
}

和 Util.java:

import android.widget.ListView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import com.example.budgetapp.R;

import java.util.logging.Logger;

public class Util extends AppCompatActivity {

   public Util(){
       System.out.println("Util Constructor");
   }

    public Toolbar getToolbar() {
        return toolbar;
    }

    public void setToolbar(Toolbar toolbar) {
        this.toolbar = toolbar;
    }

    public ListView getListView() {
        return listView;
    }

    public void setListView(ListView listView) {
        this.listView = listView;
    }

    @Override
    public String toString() {
        return "Util{" +
                "toolbar=" + toolbar +
                ", listView=" + listView +
                '}';
    }

    private Toolbar toolbar;
    private ListView listView;
    Logger logger;

        public void setupUIViews(){
            toolbar = findViewById(R.id.ToolbarMain);
            logger.info("inside Util class, setupUiViews, before findViewById(lvMain)");
            listView = findViewById(R.id.lvMain);
        }

        public void initToolbar(){
            setSupportActionBar(toolbar);
            getSupportActionBar().setTitle(" App");
        }

        public void setupListView(){
            String[] title = getResources().getStringArray(R.array.Main);
            String[] description=getResources().getStringArray(R.array.Description);

            SimpleAdapter simpleAdapter = new SimpleAdapter(this, title, description);
            listView.setAdapter(simpleAdapter);
        }
}

代码在从 Util 类进入 setupUIViews() 方法之前就崩溃了。

请你看看,告诉我如何解决这个问题?

我调试了,但不明白问题出在哪里。

另外,查看了其他类似的问题,但每个示例都是特定的,所以我无法推断我的情况。

非常感谢您的宝贵时间和帮助!

【问题讨论】:

    标签: java android nullpointerexception


    【解决方案1】:

    你调用 util. setupUIViews(),在内部方法中,它调用了findViewById(R.id.ToolbarMain)。该方法属于Activity,我们看源码

    return getWindow().findViewById(id);
    
    //in the window, (PhoneWindow)
    @Nullable
        public <T extends View> T findViewById(@IdRes int id) {
            return getDecorView().findViewById(id);
        }
    // the DecorView is the basic view, it set when you call setContentView
    public void setContentView(@LayoutRes int layoutResID) {
            getWindow().setContentView(layoutResID);
            initWindowDecorActionBar();
        }
    //PhoneWindow setContentView
    @Override
        public void setContentView(View view) {
            setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
        }
    @Override
        public void setContentView(View view, ViewGroup.LayoutParams params) {
      // decor, when theme attributes and the like are crystalized. Do not 
      // check the feature
            // before this happens.
            if (mContentParent == null) {
                installDecor(); // this method init DecorView
           } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
                mContentParent.removeAllViews();
            }
    ...
    }
    
    

    但你不调用 util setContenView 来设置它的视图。所以它会报告错误。

    而且您的代码编写方式是错误的。我们在活动或片段自己的类中设置视图; 我们不能使用另一个活动来设置其他活动。

    在 android 中,每个活动都有自己的窗口。尝试将 Utils 方法移入 MainActiviy。

    【讨论】:

    • 嗨 Lenoarod,“在 android 中,每个活动都有自己的窗口。尝试将 Utils 方法移动到 MainActiviy。”。非常到位!我现在明白我的问题了。好吧,我使用了快捷方式,因为我没有成功地将 Java 代码转换为 Kotlin 代码。所以我创建了一个新类,以便能够在那里使用我拥有的 Java 代码。不工作!或许你能帮我找到解决办法?这是Java代码,我的问题是声明和初始化列表。我查看了文档,但在进行更改后,我的代码仍然没有编译
    • 这里是 Java 代码: public void setupListView(){ String[] title = getResources().getStringArray(R.array.Main); String[] 描述=getResources().getStringArray(R.array.Description); SimpleAdapter simpleAdapter = new SimpleAdapter(this, title, description); listView.setAdapter(simpleAdapter);它真的对我有很大帮助!谢谢
    • @Léa,如果您的意思是列表不显示。原因在于适配器getView。 if(convertView == null) { layoutInflater.inflate(R.layout.main_activity_single_item, null); },您没有返回视图。你可以看到这个答案(stackoverflow.com/a/8693597/5705408)了解更多详情
    • @Léa,同时,今天我们经常使用recyclerView。这对列表更好。
    • 好的,我会仔细看看你给我的链接和参考。您在自己的窗口中进行每项活动是正确的。我会接受你的回答,这真的很有帮助!在meanteam中,我成功地从Java转换为Kotlin(对于那些与我有同样问题的人),这对我有用:private fun setupListView(){ val title = resources.getStringArray(R.array.Main ) val description=resources.getStringArray(R.array.Description) var simpleAdapter= SimpleAdapter(this, title, description) listView.setAdapter(simpleAdapter);}
    【解决方案2】:

    util 类是从 AppCompatActivity 扩展的,但未正确初始化。您不能以这种方式使用 AppCompatActivity。相反,您需要执行以下操作:

    class MainActivity : AppCompatActivity() {
        private val tag = "MainActivity"
        lateinit var util: Util
    
        override fun onCreate(savedInstanceState: Bundle?) {
            util  = Util(this)
        }
    }
    

    还有 Util(在 kotlin 中)类:

    class Util(private delegate:MainActivity) {
        public void setupUIViews(){
            toolbar = delegate.findViewById(R.id.ToolbarMain);
            listView = delegate.findViewById(R.id.lvMain);
        }
    }
    

    另外,我认为使用这种模式并将所有与视图相关的内容移动到“Util”类并不是最好的。使用 MVP 或 MVVM 等其他模式将获得更好的结果。

    【讨论】:

    • 谢谢 Ricardo Markiewicz,我同意单独的 Util 类不是最好的主意。即使使用了您提供的建议,程序也无法编译,即使代码是正确的(正如我对 Kotlin 的了解,这并不多)。我将在 MainActivity 中更改 Util 中的方法,如教程中所述以及您所暗示的那样。谢谢您的回复,先生!很棒的建议
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-23
    • 1970-01-01
    • 2017-04-10
    • 2013-11-14
    • 2014-05-12
    相关资源
    最近更新 更多