在android中使用Loaders的简单代码出错

时间:2017-07-09 15:22:30

标签: android loader

我试图重构我的代码并将我的代码从Async Task移动到加载器。我通过Android Performance视频系列this了解了加载器的好处 我知道为什么使用装载机以及它有什么类和东西(理论)。但是我无法掌握工作概念,因此编写了这个糟糕的代码。因此我也无法调试它。 **编辑:我能够使它工作,但我仍然认为我以错误的方式调用它。

new EarthquakeAsyncTaskLoader(this).forceLoad();

如果有人可以帮助我,请......... **

import android.content.AsyncTaskLoader;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;

import java.io.IOException;
import java.util.ArrayList;

public class EarthQuakeActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<ArrayList<EarthQuakes>> {

ArrayList<EarthQuakes> earthquakes = null;


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

    getSupportLoaderManager().initLoader(1, null, this);

}// End of onCreate

@Override
public Loader<ArrayList<EarthQuakes>> onCreateLoader(int id, Bundle args) {

    **new EarthquakeAsyncTaskLoader(this).forceLoad();**
}

@Override
public void onLoadFinished(Loader<ArrayList<EarthQuakes>> loader, ArrayList<EarthQuakes> data) {
}

@Override
public void onLoaderReset(Loader<ArrayList<EarthQuakes>> loader) {

}


public class EarthquakeAsyncTaskLoader extends AsyncTaskLoader<ArrayList<EarthQuakes>> {

    public EarthquakeAsyncTaskLoader(Context context) {
        super(context);
    }


    @Override
    protected void onStartLoading() {
        // If the data is there, don't start again
        if (earthquakes != null) {
            deliverResult(earthquakes);
        } else {
            //Start the loader
            forceLoad();
        }
    }

    @Override
    public ArrayList<EarthQuakes> loadInBackground() {
        // Get the populated list from QueryUtils java class
        try {
           // Here in QueryUtils, I am making an HTTP network call
           // Thus it has to be done in a helper background thread
            earthquakes = QueryUtils.getArrayList();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return earthquakes;
    }


    @Override
    public void deliverResult(ArrayList<EarthQuakes> data) {

        // Feed the adapter with data and display it
        ListView earthquakesList = (ListView) findViewById(R.id.listV);
        final EarthQuakeAdapter adapter = new EarthQuakeAdapter(getApplicationContext(), data);
        earthquakesList.setAdapter(adapter);

        earthquakesList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                EarthQuakes currentEarthquake = adapter.getItem(i);
                Uri earthquakeUri = Uri.parse(currentEarthquake.getUrl());

        // Create a new intent to view the earthquake URI
                Intent websiteIntent = new Intent(Intent.ACTION_VIEW, earthquakeUri);

        // Send the intent to launch a new activity
                startActivity(websiteIntent);
            }
        });

    }
}//End of Async Task Loader


//EarthQuakes is my class. I don't think you'll need this. But anyway:
public class EarthQuakes {


    private double mMagnitude;
    private String mLocationSmallText;
    private String mLocationMainText;
    private String mDateOfEarthquake;
    private String mUrl;


    // Default Constructor
    public EarthQuakes(Double mag, String locationSmallText, String locationMainCityName, String dateE, String Url) {
        this.mMagnitude = mag;
        this.mLocationSmallText = locationSmallText;
        this.mLocationMainText = locationMainCityName;
        this.mDateOfEarthquake = dateE;
        this.mUrl = Url;
    }


    // Public getters
    public Double getMagnitude() {
        return mMagnitude;
    }

    public String getLocationSmallTextEarthquake() {
        return mLocationSmallText;
    }

    public String getLocationLargeTextEarthquake() {
        return mLocationMainText;
    }

    public String getDateOfEarthquake() {
        return mDateOfEarthquake;
    }

    public String getUrl() {
        return mUrl;
    }

}

1 个答案:

答案 0 :(得分:0)

此替代方案也有效:

getSupportLoaderManager().initLoader(1, null, this).forceload();

但是,这只是提及here加载器问题的一种方法。 如果您使用的AsyncTaskLoader不是CursorLoader,则会出现此问题。 您需要实现onStartLoading()并在那里处理调用forceLoad()。强烈建议您浏览问题页面。

如果您在整个应用中使用多个加载器,并且不希望每次都实现onStartLoading()。这是一个自定义加载器类,您可以将其包含在您的应用中,并从此继承,而不是通常的AsyncTaskLoader

WrappedAsyncTaskLoader.java(原作者:Alexander Blom)

public abstract class WrappedAsyncTaskLoader<D> extends AsyncTaskLoader<D> {

private D mData;

/**
 * Constructor of <code>WrappedAsyncTaskLoader</code>
 *
 * @param context The {@link Context} to use.
 */
public WrappedAsyncTaskLoader(Context context) {
    super(context);
}

/**
 * {@inheritDoc}
 */
@Override
public void deliverResult(D data) {
    if (!isReset()) {
        this.mData = data;
        super.deliverResult(data);
    } else {
        // An asynchronous query came in while the loader is stopped
    }
}

/**
 * {@inheritDoc}
 */
@Override
protected void onStartLoading() {
    super.onStartLoading();
    if (this.mData != null) {
        deliverResult(this.mData);
    } else if (takeContentChanged() || this.mData == null) {
        forceLoad();
    }
}

/**
 * {@inheritDoc}
 */
@Override
protected void onStopLoading() {
    super.onStopLoading();
    // Attempt to cancel the current load task if possible
    cancelLoad();
}

/**
 * {@inheritDoc}
 */
@Override
protected void onReset() {
    super.onReset();
    // Ensure the loader is stopped
    onStopLoading();
    this.mData = null;
}
}