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

Android Studio自定义ListView加载JSON致应用崩溃求助

解决自定义ListView加载JSON时的崩溃问题

看起来你遇到的崩溃大概率是由空指针异常导致的,我帮你梳理了代码里的几个关键问题,逐个修复就能解决:


1. 自定义适配器(CustomAdapter)中的空指针问题

你的CustomAdapter里声明了ArrayListCountries,但从未在构造函数中初始化赋值,导致调用getView()时ArrayListCountries.get(Position)直接抛出空指针,这是最可能的崩溃原因。

修复后的CustomAdapter代码:

public class CustomAdapter extends ArrayAdapter<Country> {
    public ArrayList<Country> ArrayListCountries;

    public CustomAdapter(@NonNull Context context, int resource, ArrayList<Country> Countries) {
        super(context, R.layout.activity_main_list, Countries);
        // 初始化成员变量,把传入的数据源赋值给ArrayListCountries
        this.ArrayListCountries = Countries;
    }

    @Override
    public View getView(int Position, View view, ViewGroup viewgroup) {
        // 复用convertView优化性能,避免每次都inflate新布局
        if (view == null) {
            LayoutInflater Inflater = LayoutInflater.from(getContext());
            view = Inflater.inflate(R.layout.activity_main_list, viewgroup, false);
        }

        // 现在可以安全获取数据了
        Country country = ArrayListCountries.get(Position);
        TextView CountryText = view.findViewById(R.id.CountryNameText);
        ImageView CountryImage = view.findViewById(R.id.CountryImage);

        CountryText.setText(country.name);
        // 补充:如果需要加载网络图片,建议用Glide/Picasso,这里先留个占位
        // Glide.with(getContext()).load(country.image).into(CountryImage);

        return view;
    }
}

2. Main类中Firebase初始化的空指针

你的FirebaseAuthentication变量没有初始化就调用getInstance(),会导致空指针:

// 原代码错误:
FirebaseInstance = FirebaseAuthentication.getInstance();
// 修复:直接初始化FirebaseInstance
FirebaseInstance = FirebaseAuth.getInstance();

修改Main类的onCreate部分:

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

    UserEmailText = findViewById(R.id.UserEmail);
    // 修复Firebase初始化
    FirebaseInstance = FirebaseAuth.getInstance();
    LoggedInUser = FirebaseInstance.getCurrentUser();

    UserEmailText.setText(LoggedInUser.getEmail());

    CountryList = new ArrayList<>();
    CountryListView = findViewById(R.id.CountryList);
    new GetCountries().execute();
}

3. 退出登录时ProgressDialog的空指针风险

在onOptionsItemSelected的退出分支里,你直接调用ProgressDialog.setMessage(),但ProgressDialog是在GetCountries的onPreExecute()中才初始化的。如果用户还没加载过列表就点退出,ProgressDialog是null,会崩溃。

修复方案:提前初始化ProgressDialog,或者在使用前判空:

// 在Main类的成员变量初始化时就创建ProgressDialog(推荐)
private ProgressDialog ProgressDialog;

@Override
protected void onCreate(Bundle savedInstanceState) {
    // ...其他代码
    ProgressDialog = new ProgressDialog(Main.this);
    ProgressDialog.setCancelable(false);
}

// 退出登录分支修改:
else if(item.getItemId() == R.id.MenuItem2){
    FirebaseAuth.getInstance().signOut();
    ProgressDialog.setMessage("Signing out...");
    ProgressDialog.show();
    // 注意:先显示弹窗再跳转,避免弹窗还没显示就finish了
    OpenBeginningActivity();
}

4. JSON解析中的异常处理优化

在doInBackground的catch块里,你直接修改ProgressDialog的消息,但doInBackground是子线程,不能直接操作UI,会导致崩溃。应该把错误消息传到onPostExecute处理:

修改GetCountries类:

private class GetCountries extends AsyncTask<Void, Void, String> {
    // 把返回类型改成String,用来传递错误信息
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        ProgressDialog.setMessage("Please wait...");
        ProgressDialog.show();
    }

    @Override
    protected String doInBackground(Void... voids) {
        HttpHandler Handler = new HttpHandler();
        String JSONString = Handler.makeServiceCall(JSONUrl);
        Log.e(TAG, "Response:" + JSONString);

        if(JSONString != null){
            try {
                JSONObject CountriesJSONObject = new JSONObject(JSONString);
                JSONArray Countries = CountriesJSONObject.getJSONArray("countries");
                for (int i = 0; i < Countries.length(); i++) {
                    JSONObject Country = Countries.getJSONObject(i).getJSONObject("country");
                    String CountryID = Country.getString("id");
                    String CountryName = Country.getString("name");
                    String CountryImage = Country.getString("image");
                    CountryList.add(new Country(CountryID, CountryName, CountryImage));
                }
                return null; // 没有错误返回null
            } catch (final JSONException e){
                Log.e(TAG,e.getMessage());
                return "Error loading Data!"; // 返回错误信息
            }
        } else {
            return "Failed to get data from server!";
        }
    }

    @Override
    protected void onPostExecute(String errorMsg) {
        ProgressDialog.dismiss();
        if(errorMsg != null){
            // 用Toast显示错误信息
            Toast.makeText(Main.this, errorMsg, Toast.LENGTH_SHORT).show();
            return;
        }
        ListAdapter CustomAdapter = new CustomAdapter(Main.this,0,CountryList);
        CountryListView.setAdapter(CustomAdapter);
    }
}

把这些修复点全部应用后,你的ListView应该就能正常加载数据,不会崩溃了。另外建议你打开Android Studio的Logcat,查看崩溃时的具体异常信息,这是调试这类问题最快的方式。

内容的提问来源于stack exchange,提问作者VallyMan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:20:48