You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android测试API应用启动崩溃排查求助(新手开发者)

问题:API测试应用启动崩溃排查

我是一名新手开发者,当前出现问题的是一款API测试应用,基于GitHub上jkutner的教程实现。此前我曾三次使用完全相同的代码且均能正常运行,但现在应用一启动就崩溃。以下是相关代码及Logcat信息,恳请协助排查问题!

MainActivity代码

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class MainActivity extends AppCompatActivity
{

    final EditText isbnInput = (EditText) findViewById(R.id.isbnInput);
    final TextView textView = (TextView) findViewById(R.id.textView);
    final Button button = (Button) findViewById(R.id.button);

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://venusdove.herokuapp.com")
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        final BookService service = retrofit.create(BookService.class);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Book book = new Book(isbnInput.getText().toString());
                Call<Book> createCall = service.create(book);
                createCall.enqueue(new Callback<Book>() {
                    @Override
                    public void onResponse(Call<Book> _, Response<Book> resp) {
                        Book newBook = resp.body();
                        textView.setText("Created Book with ISBN: " + newBook.isbn);
                    }

                    @Override
                    public void onFailure(Call<Book> _, Throwable t) {
                        t.printStackTrace();
                        textView.setText(t.getMessage());
                    }
                });
            }
        });
    }
}

Book类代码

package com.example.myapplication;

import com.google.gson.annotations.SerializedName;

public class Book
{
    @SerializedName("id")
    int id;

    @SerializedName("isbn")
    String isbn;

    public Book(int id, String isbn) {
        this.id = id;
        this.isbn = isbn;
    }

    public Book(String isbn) {
        this.isbn = isbn;
    }
}

BookService接口代码

package com.example.myapplication;

import java.util.List;

import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Path;

public interface BookService
{
    @GET("books")
    Call<List<Book>> all();

    @GET("books/{isbn}")
    Call<Book> get(@Path("isbn") String isbn);

    @POST("books/new")
    Call<Book> create(@Body Book book);
}

Logcat错误信息

2022-10-19 08:56:03.651 8041-8041/com.example.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.myapplication, PID: 8041
    java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.myapplication/com.example.myapplication.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:2679)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
        at android.app.ActivityThread.-wrap11(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6494)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
     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:152)
        at android.view.ContextThemeWrapper.getTheme(ContextThemeWrapper.java:157)
        at android.content.Context.obtainStyledAttributes(Context.java:655)
        at androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor(AppCompatDelegateImpl.java:852)
        at androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor(AppCompatDelegateImpl.java:819)
        at androidx.appcompat.app.AppCompatDelegateImpl.findViewById(AppCompatDelegateImpl.java:640)
        at androidx.appcompat.app.AppCompatActivity.findViewById(AppCompatActivity.java:261)
        at com.example.myapplication.MainActivity.<init>(MainActivity.java:22)
        at java.lang.Class.newInstance(Native Method)
        at android.app.Instrumentation.newActivity(Instrumentation.java:1174)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2669)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856) 
        at android.app.ActivityThread.-wrap11(Unknown Source:0) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:164) 
        at android.app.ActivityThread.main(ActivityThread.java:6494) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

问题分析与修复

崩溃原因

错误日志明确显示,findViewById调用在MainActivity的构造阶段执行,此时Activity的上下文还未初始化,调用findViewById会触发空指针异常。

在Android Activity生命周期中,findViewById必须在setContentView之后调用——只有加载布局文件后,视图控件才会被实例化,才能通过ID找到对应的控件。你之前把控件初始化放在类成员变量的位置,这会在Activity对象创建时就执行,早于onCreate里的setContentView,所以必然崩溃。

修改后的MainActivity代码

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class MainActivity extends AppCompatActivity
{
    // 仅声明控件变量,不初始化
    EditText isbnInput;
    TextView textView;
    Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // 在setContentView之后初始化所有控件
        isbnInput = findViewById(R.id.isbnInput);
        textView = findViewById(R.id.textView);
        button = findViewById(R.id.button);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://venusdove.herokuapp.com")
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        final BookService service = retrofit.create(BookService.class);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Book book = new Book(isbnInput.getText().toString());
                Call<Book> createCall = service.create(book);
                createCall.enqueue(new Callback<Book>() {
                    @Override
                    public void onResponse(Call<Book> _, Response<Book> resp) {
                        Book newBook = resp.body();
                        // 增加空判断,避免服务器返回空响应时崩溃
                        if (newBook != null) {
                            textView.setText("Created Book with ISBN: " + newBook.isbn);
                        } else {
                            textView.setText("Failed to retrieve book data");
                        }
                    }

                    @Override
                    public void onFailure(Call<Book> _, Throwable t) {
                        t.printStackTrace();
                        textView.setText(t.getMessage());
                    }
                });
            }
        });
    }
}

额外优化说明

  • 移除控件变量的final修饰符:在onCreate中初始化后,后续使用不会有问题,去掉final更灵活。
  • 添加resp.body()空判断:网络请求成功时,服务器可能返回空响应,直接访问newBook.isbn会触发新的空指针异常,添加判断提升应用稳定性。

内容的提问来源于stack exchange,提问作者Laurão etc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 11:15:30