从 AsyncTask 更新 setListAdapter
Posted
技术标签:
【中文标题】从 AsyncTask 更新 setListAdapter【英文标题】:updating setListAdapter from AsyncTask 【发布时间】:2015-11-24 19:57:20 【问题描述】:我正在使用这个Tutorial 和它的sourcecodes 在android 中制作listview。我已经使用本教程实现了,但在更新setListAdapter
期间,我无法动态更新listview
。
我经历了许多 *** 问题,他们给出了adapter.notifyDataSetChanged()
作为解决方案。但我无法在 AsyncTask 中实现它。
ItemListFragment.java
public class ItemListFragment extends ListFragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
View v = super.onCreateView(inflater, container, savedInstanceState);
setListAdapter(new ItemAdapter(getActivity(), setArray(getActivity())));
return v;
public ArrayList<Item> setArray(Context context)
ArrayList<Item> items = new ArrayList<Item>();
Realm realm = Realm.getInstance(context);
RealmResults<Books> bs = realm.where(Books.class).findAll();
for (int i = 0; i < bs.size(); i++)
Bitmap url = BitmapFactory.decodeFile(bs.get(i).getCover());
String title = bs.get(i).getName();
String description = bs.get(i).getAuthor();
Item item = new Item(url, title, description);
items.add(item);
realm.close();
return items;
ItemAdapter.java
public class ItemAdapter extends ArrayAdapter<Item>
public ItemAdapter(Context context, List<Item> items)
super(context, 0, items);
public View getView(int position, View convertView, ViewGroup parent)
ItemView itemView = (ItemView) convertView;
if (null == itemView)
itemView = ItemView.inflate(parent);
itemView.setItem(getItem(position));
return itemView;
MainActivity.java
public class MainActivity extends AppCompatActivity
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
if (BuildConfig.DEBUG)
ViewServer.get(this).addWindow(this);
@Override
public boolean onCreateOptionsMenu(Menu menu)
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
@Override
public boolean onOptionsItemSelected(MenuItem item)
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings)
return true;
else if (id == R.id.update)
Update update = new Update(getApplicationContext(), MainActivity.this);
update.execute();
return true;
return super.onOptionsItemSelected(item);
@Override
protected void onDestroy()
super.onDestroy();
if (BuildConfig.DEBUG)
ViewServer.get(this).removeWindow(this);
@Override
protected void onResume()
super.onResume();
if (BuildConfig.DEBUG)
ViewServer.get(this).setFocusedWindow(this);
Update.java
public class Update extends AsyncTask<Void,Void,Void>
private Context context;
public Activity activity;
public Update(Context context, Activity activity)
this.context = context;
this.activity = activity;
@Override
protected Void doInBackground(Void... params)
ServerAddress = context.getString(R.string.ServerAddress);
StringExtras = context.getString(R.string.CheckBook);
Realm realm = null;
try
URL url = new URL(ServerAddress + StringExtras);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setRequestProperty("Content-length", "0");
httpURLConnection.setUseCaches(false);
httpURLConnection.setAllowUserInteraction(false);
httpURLConnection.setConnectTimeout(1000);
httpURLConnection.setReadTimeout(1000);
httpURLConnection.connect();
int responseCode = httpURLConnection.getResponseCode();
Log.i("Response Code",responseCode+"");
BufferedReader br = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
String InputLine;
StringBuilder response = new StringBuilder();
while ((InputLine = br.readLine()) != null)
response.append(InputLine);
br.close();
httpURLConnection.disconnect();
Log.i("Response Data", response.toString());
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
JSONArray array = new JSONArray(response.toString());
//booksList = Arrays.asList(books);
//JSONArray jsonArray = object.getJSONArray("cover");
realm = Realm.getInstance(context);
for (int i=0; i< array.length(); i++ )
JSONObject object = array.getJSONObject(i);
Books books = gson.fromJson(object.toString(), Books.class);
Publish(books, realm);
catch (Exception e)
e.printStackTrace();
finally
if (realm != null)
realm.close();
return null;
@Override
protected void onPostExecute(Void aVoid)
super.onPostExecute(aVoid);
//i want to call the setarray that contains my database data which has been updated on `doinbackground` and update the listview accordingly.
//The below codes are just the codes that i have tried but what should i do to update the listview.
activity.runOnUiThread(new Runnable()
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public void run()
ItemListFragment activity1 = new ItemListFragment();
ArrayList<Item> arrayList = activity1.setArray(context);
List<Item> list = new ArrayList<Item>();
int i = 0;
for (Item item : arrayList)
list.add(arrayList.get(i));
i++;
activity1.arrayAdapter.addAll(list);
activity1.arrayAdapter.notifyDataSetChanged();
);
我正在尝试从执行后更新列表视图。那么,如何通过它更新视图。
来自 AsyncTask 的错误
只是以防万一你需要,但这不是问题
8-30 16:31:47.976 1167-1167/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
at np.com.thefourthgeneration.Update$1.run(Update.java:124)
at android.app.Activity.runOnUiThread(Activity.java:4673)
at np.com.thefourthgeneration.Update.onPostExecute(Update.java:108)
at np.com.thefourthgeneration.Update.onPostExecute(Update.java:34)
at android.os.AsyncTask.finish(AsyncTask.java:631)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5103)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
【问题讨论】:
你不需要在 onPostExecute 方法中编写 runOnUiThread,因为 onPostExecute 运行在主线程上。只需在 onPostExecute 中调用 notifyDataSetChanged。 notifDataSetChanged() 不适合你吗? 您要创建 ItemListFragment 的新实例是为了什么?几次创建 ArrayList?在哪里放置类更新 - 在活动中? Whats the problem - you can
t 清除适配器,或者无法更新它或重新出现一些错误?提供更多代码并具体说明问题。
我会建议您阅读更多有关 android 后台服务的信息。 developer.android.com/reference/android/os/AsyncTask.html
@umerk44 是的 notifyDataSetChanged() 方法不起作用。
【参考方案1】:
布局/活动列表
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:orientation="vertical">
<FrameLayout
android:id="@+id/content_frame"
android:layout_
android:layout_/>
</LinearLayout>
layout/list_fragment
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:orientation="vertical">
<ListView
android:id="@+id/listView"
android:layout_
android:layout_/>
</LinearLayout>
MainActivity
public class MainActivity extends AppCompatActivity
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
FragmentManager fm = getFragmentManager();
itemListFragment = (ItemListFragment) fm.findFragmentByTag(ItemListFragment.class.getSimpleName());
if (itemListFragment == null)
itemListFragment = new ItemListFragment();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.content_frame, itemListFragment, ItemListFragment.class.getSimpleName());
fragmentTransaction.commit();
if (BuildConfig.DEBUG)
ViewServer.get(this).addWindow(this);
@Override
protected void onDestroy()
super.onDestroy();
if (BuildConfig.DEBUG)
ViewServer.get(this).removeWindow(this);
@Override
protected void onResume()
super.onResume();
if (BuildConfig.DEBUG)
ViewServer.get(this).setFocusedWindow(this);
ItemListFragment
public class ItemListFragment extends Fragment
private ListView listView;
private ItemAdapter itemAdapter;
private ArrayList<Item> itemArrayList = new ArrayList<>();
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setRetainInstance(true);
setHasOptionsMenu(true);
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
View view = inflater.inflate(R.layout.list_fragment, container, false);
itemAdapter = new ItemAdapter(getActivity(), itemArrayList);
listView = (ListView) view.findViewById(R.id.listView);
listView.setAdapter(itemAdapter);
return view;
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
inflater.inflate(R.menu.menu_main, menu);
@Override
public boolean onOptionsItemSelected(MenuItem item)
switch (item.getItemId())
case R.id.action_settings:
return true;
case R.id.update:
new Update(getActivity()).execute();
return true;
default:
return super.onOptionsItemSelected(item);
public class Update extends AsyncTask<Void, Void, Void>
private Context context;
public Update(Context context)
this.context = context;
@Override
protected Void doInBackground(Void... params)
ServerAddress = context.getString(R.string.ServerAddress);
StringExtras = context.getString(R.string.CheckBook);
Realm realm = null;
try
URL url = new URL(ServerAddress + StringExtras);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setRequestProperty("Content-length", "0");
httpURLConnection.setUseCaches(false);
httpURLConnection.setAllowUserInteraction(false);
httpURLConnection.setConnectTimeout(1000);
httpURLConnection.setReadTimeout(1000);
httpURLConnection.connect();
int responseCode = httpURLConnection.getResponseCode();
Log.i("Response Code", responseCode + "");
BufferedReader br = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
String InputLine;
StringBuilder response = new StringBuilder();
while ((InputLine = br.readLine()) != null)
response.append(InputLine);
br.close();
httpURLConnection.disconnect();
Log.i("Response Data", response.toString());
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
JSONArray array = new JSONArray(response.toString());
//booksList = Arrays.asList(books);
//JSONArray jsonArray = object.getJSONArray("cover");
realm = Realm.getInstance(context);
for (int i = 0; i < array.length(); i++)
JSONObject object = array.getJSONObject(i);
Books books = gson.fromJson(object.toString(), Books.class);
Publish(books, realm);
catch (Exception e)
e.printStackTrace();
finally
if (realm != null)
realm.close();
return null;
@Override
protected void onPostExecute(Void aVoid)
itemArrayList.clear();
itemArrayList.addAll(getArray(context));
itemAdapter.notifyDataSetChanged();
public ArrayList<Item> getArray(Context context)
ArrayList<Item> items = new ArrayList<Item>();
Realm realm = Realm.getInstance(context);
RealmResults<Books> bs = realm.where(Books.class).findAll();
for (int i = 0; i < bs.size(); i++)
Bitmap url = BitmapFactory.decodeFile(bs.get(i).getCover());
String title = bs.get(i).getName();
String description = bs.get(i).getAuthor();
Item item = new Item(url, title, description);
items.add(item);
realm.close();
return items;
public class ItemAdapter extends ArrayAdapter<Item>
public ItemAdapter(Context context, List<Item> items)
super(context, 0, items);
public View getView(int position, View convertView, ViewGroup parent)
ItemView itemView = (ItemView) convertView;
if (null == itemView)
itemView = ItemView.inflate(parent);
itemView.setItem(getItem(position));
return itemView;
它不是 100% 的工作代码,因为我不完全理解所有结构(如 Realm)并且我不测试它,但它是主要思想。
【讨论】:
您是如何访问itemArrayList
的class ItemListFragment
即private
的,您能解释一下吗?
@ParadiN itemArrayList 它是 ItemListFragment 的私有成员,并且 ItemListFragment 具有 itemArrayList 的完全访问权限。我将所有代码移动到片段中 - 更新和适配器类放置在 ItemListFragment 中,并且还可以访问外部类(ItemListFragment)的私有成员。所以你不需要引用 Activity 或其他东西——所有工作都在 ItemListFragment 中执行。如果您需要访问其他片段中的 itemArrayList - 您可以通过 Activity 传输它 (itemArrayList)。
@Paladin 你试过这个代码吗?你试着去理解它吗?对你有帮助吗?如果您真的需要,我编写此代码来帮助您。不适合你,只是看着这个然后说“哦,无论如何......”
我有点忙于做其他事情,所以我没有尝试过。我明天会尽力回复你。以上是关于从 AsyncTask 更新 setListAdapter的主要内容,如果未能解决你的问题,请参考以下文章
从两个不同的 AsyncTask 更新一个 ListView
重新创建活动时如何从 AsyncTask 更新 TextView
从 AsyncTask 滞后 UI 更新 ProgressBar