Я столкнулся с проблемой при попытке реализовать AsyncTask (для получения данных с сайта USGS). Я создал адаптер для работы с данными и представлением моего переработчика.
До реализации AsyncTask у меня уже был заполненный массив данных ArrayList, и он работал нормально. Теперь я хочу сделать запрос динамическим, выбирая данные из интернета. Итак, я реализовал AsyncTask, но я думаю, что я делаю это неправильно, и, кстати, у меня пустая страница, когда я запускаю приложение.
EarthQuakeActivity.java
public class EarthquakeActivity extends AppCompatActivity {
private List<EarthQuake> mEarthQuakes = new ArrayList<>();
private static final String USGS_URL =
"https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&eventtype=" +
"earthquake&orderby=time&minmag=5&limit=10";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.earthquake_activity);
RecyclerView mEarthQuakeRecyclerView;
RecyclerView.Adapter earthQuakeAdapter;
// Lookup the recyclerview in activity layout
mEarthQuakeRecyclerView = (RecyclerView) findViewById(R.id.list_recycler_view);
// Use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
mEarthQuakeRecyclerView.setHasFixedSize(true);
// Set layout manager to position the items
mEarthQuakeRecyclerView.setLayoutManager(new LinearLayoutManager(this));
// Start the AsyncTask to fetch the earthquake data
EarthQuakeAsyncTask earthQuakeAsyncTask = new EarthQuakeAsyncTask();
earthQuakeAsyncTask.execute(USGS_URL);
// Create adapter passing in the sample user data
// Third argument is a new OnItemClickListener defining the onItemClick() method behavior
earthQuakeAdapter = new EarthQuakeAdapter(
mEarthQuakes,
this,
new OnItemClickListener() {
@Override
public void onItemClick(View v, int position) {
// Get the url string of the earthquake item at position position
String url = mEarthQuakes.get(position).getmURL();
// Define a new intent to browse the url of the specific item
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
// Start the intent
startActivity(intent);
}
});
// Attach the adapter to the recyclerview to populate items
mEarthQuakeRecyclerView.setAdapter(earthQuakeAdapter);
}
/**
* AsyncTask to perform the network request on a background thread, and then
* update the UI with the list of earthquakes in the response.
* AsyncTask has three generic parameters: the input type, a type used for progress updates, and
* an output type. Our task will take a String URL, and return an Earthquake List. We won't do
* progress updates, so the second generic is just Void.
* We'll only override two of the methods of AsyncTask: doInBackground() and onPostExecute().
* The doInBackground() method runs on a background thread, so it can run long-running code
* (like network activity), without interfering with the responsiveness of the app.
* Then onPostExecute() is passed the result of doInBackground() method, but runs on the
* UI thread, so it can use the produced data to update the UI.
*/
public class EarthQuakeAsyncTask extends AsyncTask<String, Void, List<EarthQuake>> {
/**
* This method runs on a background thread and performs the network request.
* We should not update the UI from a background thread, so we return a list of
* EarthQuake(s) as the result.
*/
@Override
protected List<EarthQuake> doInBackground(String... urls) {
// Don't perform the request if there are no URLs, or the first URL is null
if (urls.length < 1 || urls[0] == null) return null;
return QueryUtils.fetchEarthquakeData(urls[0]);
}
/**
* This method runs on the main UI thread after the background work has been
* completed. This method receives as input, the return value from the doInBackground()
* method.
*/
@Override
protected void onPostExecute(final List<EarthQuake> list) {
mEarthQuakes.clear();
mEarthQuakes.addAll(list);
}
}
EarthQuakeAdapter.java
public class EarthQuakeAdapter extends RecyclerView.Adapter<EarthQuakeAdapter.ViewHolder> {
/** Privates attributes */
// Define a member variable to store the context
private Context mContext;
// Define a member variable to store the earth quakes
private List<EarthQuake> mEarthQuakes;
// Define a member variable to set up the listener
private OnItemClickListener mListener;
/** Public constructors */
// Default constructor with no parameters
public EarthQuakeAdapter() {}
// Default constructor with parameters (we pass in the earthQuakes array into the constructor)
public EarthQuakeAdapter(List<EarthQuake> earthQuakes,
Context context,
OnItemClickListener listener) {
this.mEarthQuakes = earthQuakes;
this.mContext = context;
this.mListener = listener;
}
/** Inner class */
// Provide a direct reference to each of the view within a data item
// Used to cache the views within the item layout for fast access
public static class ViewHolder extends RecyclerView.ViewHolder {
// Your holder should contain a member variable for any view that will be set as you
// render a row
private TextView magnitudeTextView;
private TextView distanceOfLocationTextView;
private TextView locationTextView;
private TextView dateTextView;
private TextView timeTextView;
// We also create a constructor (by design) that accepts the entire item row
// and does the view lookups to find each subview
public ViewHolder(View itemView) {
// Stores the itemView in a public final member variable that can be used
// to access the context from any ViewHolder instance
super(itemView);
magnitudeTextView = (TextView) itemView.findViewById(R.id.magnitude_text_view);
distanceOfLocationTextView =
(TextView) itemView.findViewById(R.id.distanceOfLocation_text_view);
locationTextView = (TextView) itemView.findViewById(R.id.location_text_view);
dateTextView = (TextView) itemView.findViewById(R.id.date_text_view);
timeTextView = (TextView) itemView.findViewById(R.id.time_text_view);
}
}
/** Methods */
// Usually involves inflating a layout from XML and returning the holder
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(mContext);
// Inflate the custom layout
View earthQuakeView =
inflater.inflate(R.layout.list_earthquake, parent, false);
// Create a new view holder
final ViewHolder earthQuakeViewHolder = new ViewHolder(earthQuakeView);
// Attach a listener on the earthQuakeView view
earthQuakeView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mListener.onItemClick(v, earthQuakeViewHolder.getAdapterPosition());
}
});
// Return a new holder instance
return earthQuakeViewHolder;
}
// Involve populating data into the item through holder
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
// Get the data model based on position
EarthQuake currentEarthQuake = mEarthQuakes.get(position);
// Call to getFormattedMagnitude to get a properly formatted magnitude string value
String magnitudeOutput = getFormattedMagnitude(currentEarthQuake.getmMagnitude());
// Set the proper background color on the magnitude circle.
// Fetch the background from the TextView, which is a GradientDrawable.
GradientDrawable magnitudeCircle =
(GradientDrawable) holder.magnitudeTextView.getBackground();
// Get the appropriate background color based on the current earthquake magnitude
int magnitudeColor = getMagnitudeColor(currentEarthQuake.getmMagnitude());
// Set the color on the magnitude circle
magnitudeCircle.setColor(magnitudeColor);
// Array that will contain the splitted location
String[] distanceOfLocation = getFormattedLocation(currentEarthQuake.getmLocation());
// Create a an object based on the item date and calls to functions to format the output
// ex formatDate : "jan 28, 2016"
// ex formatTime : "10:40"
Date dateObject = new Date(currentEarthQuake.getmDate());
String dateToDisplay = formatDate(dateObject);
String timeToDisplay = formatTime(dateObject);
// Set item views based on the view and data model
holder.magnitudeTextView.setText(magnitudeOutput);
holder.distanceOfLocationTextView.setText(distanceOfLocation[0]);
holder.locationTextView.setText(distanceOfLocation[1]);
holder.dateTextView.setText(dateToDisplay);
holder.timeTextView.setText(timeToDisplay);
}...
Любая идея о том, как реализовать это, была бы очень полезной.
При необходимости я могу загрузить полный код на GitHub.
PS: я использую интерфейс для определения поведения стандартного метода onClick из View.OnClickListener
OnItemClickListener
public interface OnItemClickListener {
void onItemClick(View v, int position);
}