我在通过从 JSON 加载产品和从产品加载图像来修复无休止的滚动时遇到了巨大的问题。我得到了两个我无法修复的错误我已经尽我所能。
当我不在最后一个项目上时,它有时会加载页面,这会给我一个“适配器已更改但列表视图未通知错误”,并且我得到一个随机的 NullPointerException ,它对我没有任何意义,我无法解决它。有什么帮助吗?
错误空指针:
03-27 10:25:29.250: E/AndroidRuntime(23494): FATAL EXCEPTION: main
03-27 10:25:29.250: E/AndroidRuntime(23494): java.lang.NullPointerException
03-27 10:25:29.250: E/AndroidRuntime(23494): at com.tonika.productlijst$ImageLoaderTask.onPostExecute(productlijst.java:761)
03-27 10:25:29.250: E/AndroidRuntime(23494): at com.tonika.productlijst$ImageLoaderTask.onPostExecute(productlijst.java:1)
03-27 10:25:29.250: E/AndroidRuntime(23494): at com.commonsware.cwac.task.AsyncTaskEx.finish(AsyncTaskEx.java:422)
03-27 10:25:29.250: E/AndroidRuntime(23494): at com.commonsware.cwac.task.AsyncTaskEx.access$300(AsyncTaskEx.java:129)
03-27 10:25:29.250: E/AndroidRuntime(23494): at com.commonsware.cwac.task.AsyncTaskEx$InternalHandler.handleMessage(AsyncTaskEx.java:434)
03-27 10:25:29.250: E/AndroidRuntime(23494): at android.os.Handler.dispatchMessage(Handler.java:99)
03-27 10:25:29.250: E/AndroidRuntime(23494): at android.os.Looper.loop(Looper.java:137)
03-27 10:25:29.250: E/AndroidRuntime(23494): at android.app.ActivityThread.main(ActivityThread.java:5234)
03-27 10:25:29.250: E/AndroidRuntime(23494): at java.lang.reflect.Method.invokeNative(Native Method)
03-27 10:25:29.250: E/AndroidRuntime(23494): at java.lang.reflect.Method.invoke(Method.java:525)
03-27 10:25:29.250: E/AndroidRuntime(23494): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:799)
03-27 10:25:29.250: E/AndroidRuntime(23494): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:566)
03-27 10:25:29.250: E/AndroidRuntime(23494): at dalvik.system.NativeStart.main(Native Method)
错误内容已更改:
03-27 10:26:48.515: E/AndroidRuntime(23630): FATAL EXCEPTION: main
03-27 10:26:48.515: E/AndroidRuntime(23630): java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. [in ListView(2131165198, class android.widget.ListView) with Adapter(class android.widget.SimpleAdapter)]
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.widget.ListView.layoutChildren(ListView.java:1544)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.widget.AbsListView.onLayout(AbsListView.java:1996)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.view.View.layout(View.java:14008)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.view.ViewGroup.layout(ViewGroup.java:4373)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.view.View.layout(View.java:14008)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.view.ViewGroup.layout(ViewGroup.java:4373)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1021)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.view.View.layout(View.java:14008)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.view.ViewGroup.layout(ViewGroup.java:4373)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.view.View.layout(View.java:14008)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.view.ViewGroup.layout(ViewGroup.java:4373)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1663)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1521)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.view.View.layout(View.java:14008)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.view.ViewGroup.layout(ViewGroup.java:4373)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.view.View.layout(View.java:14008)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.view.ViewGroup.layout(ViewGroup.java:4373)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1892)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1711)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:989)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4351)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.view.Choreographer.doCallbacks(Choreographer.java:562)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.view.Choreographer.doFrame(Choreographer.java:532)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.os.Handler.handleCallback(Handler.java:725)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.os.Handler.dispatchMessage(Handler.java:92)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.os.Looper.loop(Looper.java:137)
03-27 10:26:48.515: E/AndroidRuntime(23630): at android.app.ActivityThread.main(ActivityThread.java:5234)
03-27 10:26:48.515: E/AndroidRuntime(23630): at java.lang.reflect.Method.invokeNative(Native Method)
03-27 10:26:48.515: E/AndroidRuntime(23630): at java.lang.reflect.Method.invoke(Method.java:525)
03-27 10:26:48.515: E/AndroidRuntime(23630): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:799)
03-27 10:26:48.515: E/AndroidRuntime(23630): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:566)
03-27 10:26:48.515: E/AndroidRuntime(23630): at dalvik.system.NativeStart.main(Native Method)
代码:
public class productlijst extends Activity {
ListView list;
String keuze = "nothing";
String filter = null;
ImageView search;
ImageView thumb;
int kf;
int c;
int o;
int set;
int currentpagee;
int products;
int check;
int working;
View footerView;
SimpleAdapter adapter;
TextView total;
TextView current;
TextView divider;
ImageButton back;
ImageButton next;
DownloadTask downloadTask;
ListViewLoaderTask listViewLoaderTask;
ImageLoaderTask imageLoaderTask;
ArrayList<HashMap<String, Object>> mylist;
ProgressBar prog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.productlijst);
//Get Bundle
Bundle extra = getIntent().getExtras();
if (extra != null) {
filter = extra.getString("keuze");
keuze = extra.getString("filter");
Log.i("keuze", filter);
}
thumb = (ImageView) findViewById(R.id.imPThumb);
search = (ImageView) findViewById(R.id.imSearch);
list = (ListView) findViewById(R.id.lvKeuze);
prog = (ProgressBar) findViewById(R.id.pbProductLijst);
mylist = new ArrayList<HashMap<String, Object>>();
prog.setVisibility(View.INVISIBLE);
downloadTask = new DownloadTask();
DownloadPage downloadPage = new DownloadPage();
c = 0;
o = 10;
currentpagee = 1;
kf = 0;
products = 0;
check = 0;
working = 0;
// Starting the download process
downloadTask.execute("http://no.nl/api/products?display=full&limit=" + c + ",10&filter[id_category_default]=" + filter);
downloadPage.execute("http://no.nl/AppScripts/GetCount.php?cat=" + filter);
list.setOnScrollListener(new OnScrollListener() {
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {}
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE) {
if (working != 1) {
if (list.getLastVisiblePosition() >= list.getCount() - o) {
Log.i("Scroll", "scroll " + c);
if (c >= products ) {
//load more list items:
Toast.makeText(getApplicationContext(), "Geen producten meer", Toast.LENGTH_SHORT).show();
} else {
working = 1;
check = 1;
kf = 1;
c = c + o;
currentpagee++;
//current.setText("" + currentpagee);
Toast.makeText(getApplicationContext(), "Producten Laden..", Toast.LENGTH_SHORT).show();
ScrollDownloadTask scrollDownloadTask = new ScrollDownloadTask();
scrollDownloadTask.execute("http://no.nl/api/products?display=full&limit=" + c + ",10&filter[id_category_default]=" + filter);
adapter.notifyDataSetChanged();
}
}
} else {
Toast.makeText(getApplicationContext(), "Nog bezig met laden", Toast.LENGTH_SHORT).show();
}
}
}
});
/** A method to download xml data from url */
private String downloadUrl(String strUrl) throws IOException {
String line = null;
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet httpPost = new HttpGet(strUrl);
Credentials creds = new UsernamePasswordCredentials("", "");
httpClient.getCredentialsProvider().setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), creds);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
line = EntityUtils.toString(httpEntity);
} catch (UnsupportedEncodingException e) {
line = "<results status=\"error\"><msg>Can't connect to server</msg></results>";
} catch (MalformedURLException e) {
line = "<results status=\"error\"><msg>Can't connect to server</msg></results>";
} catch (IOException e) {
line = "<results status=\"error\"><msg>Can't connect to server</msg></results>";
}
return line;
}
private String downloadUrlPage(String strUrl) throws IOException {
String line = null;
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet httpPost = new HttpGet(strUrl);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
line = EntityUtils.toString(httpEntity);
} catch (UnsupportedEncodingException e) {
line = "<results status=\"error\"><msg>Can't connect to server</msg></results>";
} catch (MalformedURLException e) {
line = "<results status=\"error\"><msg>Can't connect to server</msg></results>";
} catch (IOException e) {
line = "<results status=\"error\"><msg>Can't connect to server</msg></results>";
}
return line;
}
/** AsyncTask to download xml data */
private class DownloadTask extends AsyncTaskEx<String, Integer, String> {
String data = null;
@Override
protected String doInBackground(String... url) {
try{
data = downloadUrl(url[0]);
} catch(Exception e) {
Log.d("Background Task",e.toString());
}
return data;
}
@Override
protected void onPostExecute(String result) {
// The parsing of the xml data is done in a non-ui thread
listViewLoaderTask = new ListViewLoaderTask();
// Start parsing xml data
listViewLoaderTask.execute(result);
}
}
下载页面代码
/** AsyncTask to download xml data */
private class DownloadPage extends AsyncTaskEx<String, Integer, String>{
String data = null;
@Override
protected String doInBackground(String... url) {
try {
data = downloadUrlPage(url[0]);
} catch(Exception e) {
Log.d("Background Task",e.toString());
}
return data;
}
@Override
protected void onPostExecute(String result) {
products = Integer.parseInt(Html.fromHtml(result).toString());
Log.i("Result page", Html.fromHtml(result).toString());
}
}
ScrollDownloadTask 的代码
/** AsyncTask to download xml data */
private class ScrollDownloadTask extends AsyncTaskEx<String, Integer, String> {
String data = null;
@Override
protected String doInBackground(String... url) {
try {
data = downloadUrl(url[0]);
} catch(Exception e) {
Log.d("Background Task",e.toString());
}
return data;
}
@Override
protected void onPostExecute(String result) {
// The parsing of the xml data is done in a non-ui thread
ScrollListViewLoaderTask ScrollListViewLoaderTask = new ScrollListViewLoaderTask();
// Start parsing xml data
ScrollListViewLoaderTask.execute(result);
}
}
ScrollListViewLoaderTaks 的代码
/** AsyncTask to parse xml data and load ListView */
private class ScrollListViewLoaderTask extends AsyncTaskEx<String, Void, SimpleAdapter> {
StringReader reader;
// Doing the parsing of xml data in a non-ui thread
@SuppressWarnings("unchecked")
@Override
protected SimpleAdapter doInBackground(String... strXml) {
DocumentBuilder db = null;
InputSource is = null;
try {
db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
is = new InputSource();
is.setCharacterStream(new StringReader(strXml[0]));
} catch(Exception e) {
Log.d("XML Exception1",e.toString());
}
Document doc = null;
try {
doc = db.parse(is);
} catch (SAXException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
NodeList nodes = doc.getElementsByTagName("product");
NodeList nodename = doc.getElementsByTagName("name");
//fill in the list items from the XML document
for (int i = 0; i < nodes.getLength(); i++) {
HashMap<String, Object> map = new HashMap<String, Object>();
Log.i("child notes", nodename.item(i).getFirstChild().getTextContent());
Element e = (Element)nodes.item(i);
Log.i("Manu name", "" + Integer.parseInt(XMLLoader.getValue(e, "quantity")));
if (Integer.parseInt(XMLLoader.getValue(e, "quantity")) > 0) {
Log.i("Stock!", "Stock!");
map.put("stock", R.drawable.stock);
} else {
map.put("stock", R.drawable.nostock);
}
String id = XMLLoader.getValue(e, "id");
String imageid = XMLLoader.getValue(e, "id_default_image");
String name = nodename.item(i).getFirstChild().getTextContent();
String newname = name;
if (newname.contains("-") | newname.contains(".") | newname.contains("'")) {
newname = newname.replaceAll("-", " ");
newname = newname.replaceAll(".", " ");
newname = newname.replaceAll("'", "");
}
String nameimage = newname.replaceAll(" ", "-");
map.put("id", id);
map.put("name", name);
map.put("imageid", imageid);
map.put("flag", R.drawable.tlogotrans);
map.put("flag_path", "http://no.nl/" + id + "-" + imageid + "-home/" + nameimage + ".jpg");
// map.put("flag_path", "http://no.nl/img/p/" + id + "-" + imageid + ".jpg");
// imageLoader.DisplayImage(, thumb);
String p = XMLLoader.getValue(e, "price");
String price = p.substring(0, p.length() - 4);
map.put("price",price);
map.put("manufacturer_name", XMLLoader.getValue(e, "manufacturer_name"));
mylist.add(map);
}
// Keys used in Hashmap
String[] from = { "name","manufacturer_name","price","flag","stock"};
// Ids of views in listview_layout
int[] to = { R.id.tvPRName,R.id.tvPLMerk,R.id.tvPRPrijs,R.id.imPThumb,R.id.imstock};
// Instantiating an adapter to store each items
// R.layout.listview_layout defines the layout of each item
adapter = new SimpleAdapter(getBaseContext(), mylist, R.layout.productlijstrow, from, to);
return adapter;
}
/** Invoked by the Android when "doInBackground" is executed */
@Override
protected void onPostExecute(SimpleAdapter adapter) {
// Setting adapter for the listview
adapter.notifyDataSetChanged();
for(int i=0;i<adapter.getCount();i++){
HashMap<String, Object> hm = (HashMap<String, Object>) adapter.getItem(i);
String imgUrl = (String) hm.get("flag_path");
imageLoaderTask = new ImageLoaderTask();
HashMap<String, Object> hmDownload = new HashMap<String, Object>();
hm.put("flag_path",imgUrl);
hm.put("position", i);
// Starting ImageLoaderTask to download and populate image in the listview
imageLoaderTask.execute(hm);
}
}
}
/** AsyncTask to parse xml data and load ListView */
private class ListViewLoaderTask extends AsyncTaskEx<String, Void, SimpleAdapter>{
StringReader reader;
// Doing the parsing of xml data in a non-ui thread
@SuppressWarnings("unchecked")
@Override
protected SimpleAdapter doInBackground(String... strXml) {
DocumentBuilder db = null;
InputSource is = null;
try{
db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
is = new InputSource();
is.setCharacterStream(new StringReader(strXml[0]));
}catch(Exception e){
Log.d("XML Exception1",e.toString());
}
Document doc = null;
try {
doc = db.parse(is);
} catch (SAXException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
NodeList nodes = doc.getElementsByTagName("product");
NodeList nodename = doc.getElementsByTagName("name");
NodeList link = doc.getElementsByTagName("link_rewrite");
//fill in the list items from the XML document
for (int i = 0; i < nodes.getLength(); i++) {
HashMap<String, Object> map = new HashMap<String, Object>();
Log.i("child notes", nodename.item(i).getFirstChild().getTextContent());
Element e = (Element)nodes.item(i);
Log.i("Manu name", "" + Integer.parseInt(XMLLoader.getValue(e, "quantity")));
if(Integer.parseInt(XMLLoader.getValue(e, "quantity")) > 0){
Log.i("Stock!", "Stock!");
map.put("stock", R.drawable.stock);
}else{
map.put("stock", R.drawable.nostock);
}
String id = XMLLoader.getValue(e, "id");
String imageid = XMLLoader.getValue(e, "id_default_image");
String name = nodename.item(i).getFirstChild().getTextContent();
String newname = link.item(i).getFirstChild().getTextContent();
map.put("id", id);
map.put("name", name);
map.put("imageid", imageid);
map.put("flag", R.drawable.tlogotrans);
//
map.put("flag_path", "http://no.nl/" + id + "-" + imageid + "-home/" + newname + ".jpg");
// map.put("flag_path", "http://no.nl/img/p/" + id + "-" + imageid + ".jpg");
// imageLoader.DisplayImage(, thumb);
String p = XMLLoader.getValue(e, "price");
String price = p.substring(0, p.length() - 4);
map.put("price",price );
map.put("manufacturer_name", XMLLoader.getValue(e, "manufacturer_name"));
mylist.add(map);
}
// Keys used in Hashmap
String[] from = { "name","manufacturer_name","price","flag","stock"};
// Ids of views in listview_layout
int[] to = { R.id.tvPRName,R.id.tvPLMerk,R.id.tvPRPrijs,R.id.imPThumb,R.id.imstock};
// Instantiating an adapter to store each items
// R.layout.listview_layout defines the layout of each item
adapter = new SimpleAdapter(getBaseContext(), mylist, R.layout.productlijstrow, from, to);
return adapter;
}
/** Invoked by the Android when "doInBackground" is executed */
@Override
protected void onPostExecute(SimpleAdapter adapter) {
// Setting adapter for the listview
list.setAdapter(adapter);
adapter.notifyDataSetChanged();
for(int i=0;i<adapter.getCount();i++){
HashMap<String, Object> hm = (HashMap<String, Object>) adapter.getItem(i);
String imgUrl = (String) hm.get("flag_path");
imageLoaderTask = new ImageLoaderTask();
HashMap<String, Object> hmDownload = new HashMap<String, Object>();
hm.put("flag_path",imgUrl);
hm.put("position", i);
// Starting ImageLoaderTask to download and populate image in the listview
imageLoaderTask.execute(hm);
}
}
}
/** AsyncTask to download and load an image in ListView */
private class ImageLoaderTask extends AsyncTaskEx<HashMap<String, Object>, Void, HashMap<String, Object>>{
@Override
protected HashMap<String, Object> doInBackground(HashMap<String, Object>... hm) {
InputStream iStream=null;
String imgUrl = (String) hm[0].get("flag_path");
int position = (Integer) hm[0].get("position");
URL url;
try {
url = new URL(imgUrl);
// Creating an http connection to communicate with url
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from url
iStream = urlConnection.getInputStream();
// Getting Caching directory
File cacheDirectory = getBaseContext().getCacheDir();
// Temporary file to store the downloaded image
File tmpFile = new File(cacheDirectory.getPath() + "/wpta_"+position+".png");
// The FileOutputStream to the temporary file
FileOutputStream fOutStream = new FileOutputStream(tmpFile);
// Creating a bitmap from the downloaded inputstream
Bitmap b = BitmapFactory.decodeStream(iStream);
// Writing the bitmap to the temporary file as png file
b.compress(Bitmap.CompressFormat.PNG,100, fOutStream);
// Flush the FileOutputStream
fOutStream.flush();
//Close the FileOutputStream
fOutStream.close();
// Create a hashmap object to store image path and its position in the listview
HashMap<String, Object> hmBitmap = new HashMap<String, Object>();
// Storing the path to the temporary image file
hmBitmap.put("flag",tmpFile.getPath());
// Storing the position of the image in the listview
hmBitmap.put("position",position);
// Returning the HashMap object containing the image path and position
return hmBitmap;
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(HashMap<String, Object> result) {
// Getting the path to the downloaded image
**String path = (String) result.get("flag");**
// Getting the position of the downloaded image
int position = (Integer) result.get("position");
// Getting adapter of the listview
SimpleAdapter adaptert = (SimpleAdapter ) list.getAdapter();
// Getting the hashmap object at the specified position of the listview
HashMap<String, Object> hm = (HashMap<String, Object>) adaptert.getItem(position);
// Overwriting the existing path in the adapter
hm.put("flag",path);
Log.i("Status", imageLoaderTask.getStatus().toString());
if(imageLoaderTask.getStatus() == AsyncTaskEx.Status.FINISHED){
check = 0;
}
// Noticing listview about the dataset changes
adaptert.notifyDataSetChanged();
working = 0;
}
}
}