You need to enable JavaScript to run this app. Android ViewModel无法解析getEarthquakes方法及UI动态更新问题求助
优惠活动
大模型
产品
解决方案
定价
更多

Android ViewModel无法解析getEarthquakes方法及UI动态更新问题求助

报错原因与修复

你在EarthquakeActivity中声明的mViewModel是父类androidx.lifecycle.ViewModel类型,父类本身没有定义getEarthquakes方法,所以编译无法识别。同时你当前的异步请求逻辑存在缺陷:网络请求是子线程异步执行,getEarthquakes直接返回时请求还未完成,拿到的永远是空值,也无法实现数据更新后自动刷新UI。


完整修改代码

1. 修改MyModel.java

用MutableLiveData包裹地震列表,添加请求标记避免屏幕旋转重复发起请求,数据变化时自动通知观察者:

package com.example.android.earthquake;

import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MyModel extends ViewModel {
    // 用LiveData包裹数据,支持观察变化
    private MutableLiveData<ArrayList<Earthquake>> mEarthquakesLiveData;
    // 标记是否已经发起过请求,避免屏幕旋转重复调用
    private boolean isFetched = false;

    public MutableLiveData<ArrayList<Earthquake>> getEarthquakesLiveData() {
        if (mEarthquakesLiveData == null) {
            mEarthquakesLiveData = new MutableLiveData<>();
        }
        // 已经请求过就不再重复发请求
        if (!isFetched) {
            fetchEarthquakeData();
            isFetched = true;
        }
        return mEarthquakesLiveData;
    }

    private void fetchEarthquakeData() {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        executorService.execute(() -> {
            // 子线程请求数据
            ArrayList<Earthquake> result = QueryUtils.fetchEarthquakeData("https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&eventtype=earthquake&orderby=time&minmag=6&limit=10");
            // 子线程用postValue更新LiveData
            mEarthquakesLiveData.postValue(result);
        });
        executorService.shutdown();
    }

    // 对外提供刷新数据的方法,需要拉取最新数据时调用即可
    public void refreshData() {
        fetchEarthquakeData();
    }
}

2. 修改EarthquakeActivity.java

把ViewModel声明为自定义的MyModel类型,观察LiveData数据变化自动更新UI:

package com.example.android.earthquake;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.app.SearchManager;
import android.content.Intent;
import android.os.Bundle;

import java.util.ArrayList;

public class EarthquakeActivity extends AppCompatActivity {

    // 声明为自定义的MyModel类型,不是父类ViewModel
    private MyModel mViewModel;
    private EarthquakeAdapter earthquakeAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.earthquake_activity);
        // 初始化ViewModel
        mViewModel = new ViewModelProvider(this).get(MyModel.class);
        // 初始化RecyclerView和适配器
        RecyclerView recyclerView = findViewById(R.id.earthquakes);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        // 初始传入空列表,后续数据返回后更新
        earthquakeAdapter = new EarthquakeAdapter(this, new ArrayList<>());
        recyclerView.setAdapter(earthquakeAdapter);

        // 观察LiveData数据变化,数据更新时自动回调
        mViewModel.getEarthquakesLiveData().observe(this, earthquakes -> {
            // 更新适配器的数据
            earthquakeAdapter.updateData(earthquakes);
            // 刷新列表
            earthquakeAdapter.notifyDataSetChanged();
            // 设置点击监听
            earthquakeAdapter.setClickListener((view, position) -> searchWeb(earthquakes.get(position).getUrl()));
        });
    }

    private void searchWeb (String url) {
        Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
        intent.putExtra(SearchManager.QUERY,url);
        if(intent.resolveActivity(getPackageManager()) != null) {
            startActivity(intent);
        }
    }
}

3. 给EarthquakeAdapter添加更新数据的方法

在你的EarthquakeAdapter类中添加如下方法,用来更新内部存储的地震列表:

public void updateData(ArrayList<Earthquake> newData) {
    // 把你适配器里原来存储地震数据的成员变量替换成新数据即可
    this.mEarthquakeList = newData;
}

API新数据自动更新UI实现

当前代码已经支持数据变化自动刷新UI,如果你需要实时拉取API最新数据,仅需要在合适的时机调用mViewModel.refreshData()即可,常见触发场景:

  • 加入下拉刷新控件,用户手动下拉时调用刷新
  • 添加定时任务,每隔固定间隔自动调用refreshData()拉取最新数据,拉取到新数据后LiveData会自动通知UI更新,不需要重启APP

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 17:15:03