【问题标题】:Callback method onLocationChanged() is not working on viewmodel回调方法 onLocationChanged() 不适用于视图模型
【发布时间】:2021-09-23 08:59:17
【问题描述】:

我正在尝试在 ViewModel 中获取位置信息。

所以我通过在 View 获取 LocationManager 来调用 requestLocationUpdates()。

我不确定 requestLocationUpdates() 在 vi​​ewmodel 中是否有效,因为回调方法 onLocationChanged() 不起作用。

我是 android 新手,所以我不知道这里出了什么问题。 因为这段代码没有错误。

我猜是因为回调方法 onLocationChanged() 没有被调用 视图模型。

如何做到这一点??

这是我的代码。

ViewModel 类

public class MAgencyViewModel extends ViewModel implements LocationListener {

    private final String TAG = "MAgencyViewModel";

    //이 클래스에서는 Model과 통신하여서 날씨 정보를 받아온다.
    private MutableLiveData<ShortWeather> sw;
    private MAgencyRepo maRepo;
    private GeoInfo gi;
    private GpsTransfer gpt;

//    public void init(GeoInfo gi) {
//        if (sw != null) {
//            return;
//        }
//
//        maRepo = MAgencyRepo.getInStance();
//        sw = maRepo.getWeather(gi); // this part is calling a weather api
//        Log.i(TAG, "API Connection finish");
//    }

    public LiveData<ShortWeather> getWeather() {
        return sw;
    }

    @SuppressLint("MissingPermission")
    //이부분은 권한 재확인 안하게 해주는 부분이다. 따로 재확인을 안하는 이유는 Activity단에서 이미 확인을 거쳤기 때문이다.
    public void locationUpdate(LocationManager lm) {
        Log.i(TAG, "locationUpdate()");
//        lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,0,0,this); //위치정보를 update하는 함수 이건 실제 기기용

        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this); //After this nothing is happening
    }

    //여기서는 이제 위치 정보가 변경 되었을때 진입하는 부분
    @Override
    public void onLocationChanged(Location location) { //This CallBack method is not working
        Log.i(TAG, "onLocationChanged()");
    }

    //위치 정보 이용 권한 허가를 받지 못했을떄 호출 하는 부분
    public void defaultLocation() {


        //GpsTransfer 객체 생성
        gpt = new GpsTransfer();

        //GpsTransfer 위도와 경도를 원주로 설정
        gpt.setxLat(76);
        gpt.setyLon(122);
        gpt.transfer(gpt, 1);

        gi = new GeoInfo();

        gi.setLon(gpt.getyLon());
        gi.setLat(gpt.getxLat());

        getTime();

        if (sw != null) {
            return;
        }

        //해당 정보를 API를 호출
        maRepo = MAgencyRepo.getInStance();
        sw = maRepo.getWeather(gi); // this part is calling a weather api
        Log.i(TAG, "API Connection finish");
    }

    public void getTime() {

        SimpleDateFormat dateSdf = new SimpleDateFormat("yyyyMMdd"); //년월일 받아오는 부분
        SimpleDateFormat timeSdf = new SimpleDateFormat("HH"); //현재시간 받아오는 부분

        Calendar cal = Calendar.getInstance(); //현재시간을 받아온다.

        gi.setNowDate(dateSdf.format(cal.getTime())); //날짜 세팅
        gi.setNowTime(timeSdf.format(cal.getTime())); //시간 세팅

        /*
         * 하루 전체의 기상예보를 받아오려면 전날 23시에 266개의 날씨정보를 호출해와야 한다.
         * 따라서 호출 값은 현재 날짜보다 1일전으로 세팅해줘야 한다.
         * */

        cal.add(Calendar.DATE, -1); //1일전 날짜를 구하기 위해 현재 날짜에서 -1 시켜주는 부분
        gi.setCallDate(dateSdf.format(cal.getTime())); //1일전 값으로 호출값 생성


        Log.i(TAG, "DATE : " + gi.getNowDate());
        Log.i(TAG, "TIME : " + gi.getNowTime());
        Log.i(TAG, "CALL DATE : " + gi.getCallDate());

    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {

    }

    @Override
    public void onProviderEnabled(String provider) {

    }

    @Override
    public void onProviderDisabled(String provider) {

    }
}

【问题讨论】:

  • 您是否尝试过使用 Google 推荐的位置请求? developer.android.com/training/location/request-updates
  • 不,我没看过@EmmanuelConradie
  • 看看下面一个ViewModel中google推荐的实现
  • 所以我必须使用 FusedLocationProviderClient 吗? @EmmanuelConradie
  • 是的,使用 LocationServices.getFusedLocationProviderClient(getApplication()).requestLocationUpdates 我更新了答案以使其更具可读性

标签: android mvvm callback viewmodel


【解决方案1】:

在你看来模型

public class MAgencyViewModel extends AndroidViewModel {
    
    private LocationCallback locationCallback;
    public boolean requestingLocationUpdates;

    public MAgencyViewModel(Application app) {
        super(app);
        locationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(LocationResult locationResult) {
                if (locationResult == null) {
                return;
                }
                for (Location location : locationResult.getLocations()) {
                    // Update UI with location data
                    // ...
                }
            }
        };
    }

    public void startLocationUpdates() {
        requestingLocationUpdates = true
        LocationServices.getFusedLocationProviderClient(getApplication())
           .requestLocationUpdates(locationRequest,
               locationCallback,
               Looper.getMainLooper());
    }

    public void stopLocationUpdates() {
        requestingLocationUpdates = false
        LocationServices.getFusedLocationProviderClient(getApplication())
        .removeLocationUpdates(locationCallback);
    }
}

现在在您的 Fragment/Activity 中覆盖暂停和恢复

然后在你的视图模型中调用 startlocation 和 stoplction

@Override
protected void onPause() {
    super.onPause();
    viewModel.stopLocationUpdates();
}
@Override
protected void onResume() {
    super.onResume();
    if (viewModel.requestingLocationUpdates) {
    startLocationUpdates();
}

如果 locationRequest 处于活动状态,请注意设置和检查布尔 requestingLocationUpdates

【讨论】:

  • 如何在 ViewModel 中使用getApplication()?我必须将context 发送到参数吗??
  • 您需要扩展 AndroidViewModel,检查更新的答案。
  • 非常感谢它帮了很多忙
猜你喜欢
  • 1970-01-01
  • 2015-08-14
  • 2016-06-30
  • 2017-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多