JSONからの製品の読み込みと製品からの画像の読み込みで無限のスクロールを修正する大きな問題があります。修正できないエラーが2つ表示されますが、できる限りのことを試しました。
「アダプターが変更されましたが、リストビューに通知されませんでした」というエラーが表示される最後の項目にいないときにページが読み込まれることがあり、何も言わずに解決できないランダムな 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);
}
}
DownloadPage のコード
/** 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;
}
}
}