我已经浏览了超过50页,为我极其简单的应用程序寻找解决方案,但似乎没有一个适合我。请帮忙。如何应用我从doInBackground()获得的数据应用于我的RecyclerView?
问题:我在MainActivity的菜单中有一个刷新按钮。当按下时,我想执行我的AsyncTask,然后更新我的RecyclerView中的所有项目。
情况。
我的应用程序通过OpenWeatherMap.org取出从API数据,然后显示这些数据。
我有一个MainActivity类别(和我recyclerView这里驻留在。)
- 对于recyclerView,我使用RecyclerView.Adapter与GridViewManager。
- 我有一个单独的AsyncTask类。
所以,我曾尝试和没有工作:
方法1.正常方式。当选择刷新按钮时,调用我的AsyncTask。在我的PostExecute()中,我在MainActivity中调用setter来从doInBackGround方法分配结果数组。
在MainActivity然后,
myAsyncTask.execute("43017,us");
recyclerView.recyclerView.getAdapter().notifyDataSetChanged();
但是这将导致notifyDataSetChanged();
之前MainActivity构件vairable阵列从onPostExecute()
更新到被调用。方法2.尝试从onPostExecute
方法中完全更新UI,请参阅MyAsyncTask.class
中的onPostExecute
方法。
那么我知道onPostExecute
,即使它被写入不同的类,在UI线程上运行。因此,在方法中,我不喜欢的东西
MainActivity mainActivity = new MainActivity();
RecyclerView recyclerView = mainActivity.findViewById(R.id.recyclerView);
RecyclerView.Adapter adapter = recyclerView.getAdapter();
adapter.notifyDataSetChanged();
在这种方法中,有记录,我已确认onPostExecute
成功更新在MainActivity成员变量,它只是notifyDataSetChanged
变得太叫早,特别是onPostExecute
前在后台完成。
我希望能为此得到一个答案,并对我的情况足够清楚。我会在下面发布我的MainActivity,Adapter和AsyncTask代码。
MainActivity.java:
public class MainActivity extends AppCompatActivity {
private String weatherData[] = {
"Today - Sunny",
"Tomorrow - Cloudy",
"Tuesday - Rainy",
"Wednesday - Sunny",
"Thursday - Sunny",
"Friday - Sunny",
"Saturday - Cloudy",
"Sunday - Rainy :/"
};
private RecyclerView recyclerView;
private mAdapter adapter;
private static final int SPAN_COUNT = 1;
private MyAsyncTask myAsyncTask = new MyAsyncTask();
private Context context;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView)findViewById(R.id.recyclerview_weatherData);
setLayout(getApplicationContext());
adapter = new mAdapter(weatherData);
recyclerView.setAdapter(adapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id){
case R.id.action_refresh:
Log.v("Menu", "Refresh button selected.");
//for now, take some random ZIP code
myAsyncTask.execute("43017,us");
recyclerView.getAdapter().notifyDataSetChanged();
adapter.refreshContents(weatherData);
for (int i = 0; i<weatherData.length; i++) {
Log.v("Refresh button", weatherData[i].toString());
}
}
return true;
}
public void setLayout(Context context) {
int scrollPosition = 0;
//make a GridLayoutManager with 2 columns
LinearLayoutManager mLayoutManager = new LinearLayoutManager(context);
//set the mLayoutManager to the one that I just created
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.scrollToPosition(scrollPosition);
recyclerView.setLayoutManager(new GridLayoutManager(context, SPAN_COUNT));
//set the offset decoration definition to my layout
int middle_spacing = 30;
boolean includeEdge = true;
recyclerView.addItemDecoration(new ItemOffsetDecoration(SPAN_COUNT, middle_spacing, includeEdge));
}
public void setWeatherData(String[] weatherData) {
this.weatherData = weatherData;
}
public String[] getWeatherData() { return weatherData; }
}
MyAsyncTask.java:
public class MyAsyncTask extends AsyncTask<String,Void,String[]> {
public final static String OPEN_WEATHER_MAP_API_KEY = "bc607b72747aa672bf2ac9a5f3a5fc84";
String forecastJsonStr = null;
private String format = "json";
private String units = "metric";
private int numDays = 7;
private String data[] =null;
private RecyclerView recyclerView;
private MainActivity mainActivity;
private RecyclerView.Adapter adapter;
@Override
protected String[] doInBackground(String... params) {
if (params.length == 0) {
Log.v("AsyncTask", "No parameter is taken.");
return null;
}
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
try {
final String FORECAST_BASE_URL = "http://api.openweathermap.org/data/2.5/forecast/daily?";
final String QUERY_PARAM = "q";
final String FORMAT_PARAM = "mode";
final String UNITS_PARAM = "units";
final String DAYS_PARAM = "cnt";
final String APPID_PARAM = "APPID";
Uri builtUri = Uri.parse(FORECAST_BASE_URL).buildUpon()
.appendQueryParameter(QUERY_PARAM, params[0])
.appendQueryParameter(FORMAT_PARAM, format)
.appendQueryParameter(UNITS_PARAM, units)
.appendQueryParameter(DAYS_PARAM, Integer.toString(numDays))
.appendQueryParameter(APPID_PARAM, OPEN_WEATHER_MAP_API_KEY)
.build();
URL url = new URL(builtUri.toString());
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
return null;
}
//put the buffer in String var forecastJsonStr
forecastJsonStr = buffer.toString();
Log.v("AsyncTask", forecastJsonStr.toString());
} catch (IOException e) {
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("Async", "Reader is null, something wrong.");
}
}
}
//Then put the string contents into an array
try {
ParseWeatherData parser = new ParseWeatherData();
data = parser.getWeatherDataFromJson(forecastJsonStr, numDays);
return data;
} catch (JSONException e) {
e.printStackTrace();
}
return data;
}
@Override
protected void onPostExecute(final String data[]) {
super.onPostExecute(data);
if (data != null) {
//this log works fine: the fetched data is successfully stored...
for (int i = 0; i<data.length; i++) {
Log.v("onPostExecute", data[i].toString());
}
//how do I pass this data to the main thread?
mainActivity = new MainActivity();
mainActivity.setWeatherData(data);
}
}
}
最后,mAdapter.java:
public class mAdapter extends RecyclerView.Adapter<mAdapter.ViewHolder> {
private String data[];
public mAdapter(String data[]) {
this.data = data;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View listView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_single_list, parent, false);
return new ViewHolder(listView);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.weather.setText(data[position]);
Log.v("BindView", "Item " + position + " set.");
}
@Override
public int getItemCount() {
if (data == null) {
Log.v("WeatherAdapter", "Oops, getting null in the adapter.");
return 0;
} else {
return data.length;
}
}
public void refreshContents(String data[]) {
this.data = null;
this.data = data;
notifyDataSetChanged();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView weather, day;
//currently ViewHolder is set as the TextView for logging
public ViewHolder(View v) {
super(v);
weather = (TextView) v.findViewById(R.id.test_text);
// Define click listener for the ViewHolder's View.
v.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "Element " + getAdapterPosition() + " clicked.");
}
});
}
}
}
预先感谢您!
写下接口回调和onPostexecute通过你的结果() 并在主要活动接收数据 –