I worked through 6 other questions about SO, plus some blog posts with the same mesage error, all to no avail.
I upload the file directory to ArrayList
and then to ListView
using ArrayAdapter
. The code really works - the directory is displayed and responds to click events - but then the program ends with this error, usually after I show the directory one, several or several times, and then run the other part of the program that does loadUrl in the WebView:
The contents of the adapter changed, but the ListView did not receive a notification. Verify that the contents of the adapter are not modified. background thread, but only from the user interface thread. Make sure the adapter calls notifyDataSetChanged () when its contents change.
None of the simple examples I saw used notifyDataSetChanged
or a separate thread. I am wondering if I need to use them and how to use them correctly. I am confused between ArrayAdapter
and ArrayList
, which should only be changed in the main thread. Data in ArrayList
changes only when a new directory is requested, then it is cleared and loaded with new data.
My questions: do I need notifyDataSetChanged? [I don’t know at all], and how can I organize the various parts between the main and the background / runnable thread?
, List
displayFtpHelp [ WebView/loadUrl()] -
, .
LogCat , ,
; :
android.widget.ListView.layoutChildren(ListView.java:1555)
displayFtpHelp loadUrl() WebView. ,
. ,
ArrayList/ArrayAdapter . ,
, .
, ListViews ArrayList.
ListView , Ftp.
static ListView filesListLocal, filesListRemote;
static ArrayList<HashMap<String,String>> directoryEntries = new ArrayList<>();
Ftp.
, , file.getAbsolutePath()
ftp.list()
lookForFilesAndDirs(),
.
Ftp Runnable.
; Ftp4j
:
Runnable r = new Runnable() {
public void run() {
Message msg = mHandler.obtainMessage();
try {
FTPFile[] fileAndDirs = ftp.list();
dirName = ftp.currentDirectory();
} catch (Various Exceptions e) {
result = "The operation failed\n" + e.toString();
}
Bundle bundle = new Bundle();
bundle.putString("mickKey", result);
msg.setData(bundle);
mHandler.sendMessage(msg);
}
};
Thread t = new Thread(r);
t.start();
ArrayList
, ListView.
Runnable,
, .
notifyDataSetChanged
,
:
dirName = ftp.currentDirectory();
sa.notifyDataSetChanged();
directoryEntries.clear();
lookForFilesAndDirs(fileAndDirs); // load ArrayList
SimpleAdapter saFtp = new SimpleAdapter(myContext, directoryEntries,
R.layout.my_two_lines, new String[] {"path", "filename"},
new int[] {R.id.path, R.id.filename});
filesListRemote.setAdapter(saFtp);
sa.notifyDataSetChanged();
...
public static void lookForFilesAndDirs(FTPFile[] fileAndDirs) {
for (FTPFile fileOrDir : fileAndDirs) {
String fileOrDirName = fileOrDir.getName();
int entryType = fileOrDir.getType();
if (entryType == 1) {
HashMap<String,String> listEntry = new HashMap<>();
listEntry.put("path", fileOrDirName);
listEntry.put("filename", null);
directoryEntries.add(listEntry);
} else {
HashMap<String,String> listEntry = new HashMap<>();
listEntry.put("path", dirName);
listEntry.put("filename", fileOrDirName);
directoryEntries.add(listEntry);
}
}
LogCat:
10-14 19:47:29.403 3006-3006/com.webs.mdawdy.htmlspyii I/Mick: onMenuItemClick
10-14 19:47:29.403 3006-3006/com.webs.mdawdy.htmlspyii I/Mick: ftpPrintFilesList
10-14 19:47:30.235 3006-3006/com.webs.mdawdy.htmlspyii I/Mick: handleMessage
10-14 19:47:32.339 3006-3006/com.webs.mdawdy.htmlspyii W/EGL_genymotion: eglSurfaceAttrib not implemented
10-14 19:47:34.627 3006-3006/com.webs.mdawdy.htmlspyii I/Mick: onMenuItemClick
10-14 19:47:34.627 3006-3006/com.webs.mdawdy.htmlspyii I/Mick: displayFtpHelp Begin
10-14 19:47:34.627 3006-3006/com.webs.mdawdy.htmlspyii I/Mick: displayFtpHelp end
10-14 19:47:34.819 3006-3006/com.webs.mdawdy.htmlspyii D/AndroidRuntime: Shutting down VM
10-14 19:47:34.819 3006-3006/com.webs.mdawdy.htmlspyii W/dalvikvm: threadid=1:
thread exiting with uncaught exception (group=0xa4d2db20)
10-14 19:47:34.823 3006-3006/com.webs.mdawdy.htmlspyii E/AndroidRuntime: FATAL EXCEPTION: main
10-14 19:47:34.823 3006-3006/com.webs.mdawdy.htmlspyii E/AndroidRuntime: Process: com.webs.mdawdy.htmlspyii, PID: 3006
10-14 19:47:34.823 3006-3006/com.webs.mdawdy.htmlspyii E/AndroidRuntime:
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.
Make sure your adapter calls notifyDataSetChanged() when its content changes.
[in ListView(2131427419, class android.widget.ListView) with
Adapter(class android.widget.SimpleAdapter)]
10-14 19:47:34.823 3006-3006/com.webs.mdawdy.htmlspyii E/AndroidRuntime: at android.widget.ListView.layoutChildren(ListView.java:1555)
10-14 19:47:34.823 3006-3006/com.webs.mdawdy.htmlspyii E/AndroidRuntime: at android.widget.ListView.setSelectionInt(ListView.java:1980)
10-14 19:47:34.823 3006-3006/com.webs.mdawdy.htmlspyii E/AndroidRuntime: at android.widget.AbsListView.resurrectSelection(AbsListView.java:5376)
10-14 19:47:34.823 3006-3006/com.webs.mdawdy.htmlspyii E/AndroidRuntime: at android.widget.AbsListView.onWindowFocusChanged(AbsListView.java:2822)
10-14 19:47:34.823 3006-3006/com.webs.mdawdy.htmlspyii E/AndroidRuntime: at android.view.View.dispatchWindowFocusChanged(View.java:7900)
10-14 19:47:34.823 3006-3006/com.webs.mdawdy.htmlspyii E/AndroidRuntime: at android.view.ViewGroup.dispatchWindowFocusChanged(ViewGroup.java:968)
10-14 19:47:34.823 3006-3006/com.webs.mdawdy.htmlspyii E/AndroidRuntime: at android.view.ViewGroup.dispatchWindowFocusChanged(ViewGroup.java:972)
[6 more lines identical to the one above]
10-14 19:47:34.823 3006-3006/com.webs.mdawdy.htmlspyii E/AndroidRuntime: at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:3133)
10-14 19:47:34.823 3006-3006/com.webs.mdawdy.htmlspyii E/AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:102)
10-14 19:47:34.823 3006-3006/com.webs.mdawdy.htmlspyii E/AndroidRuntime: at android.os.Looper.loop(Looper.java:136)
10-14 19:47:34.823 3006-3006/com.webs.mdawdy.htmlspyii E/AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:5001)
10-14 19:47:34.823 3006-3006/com.webs.mdawdy.htmlspyii E/AndroidRuntime: at java.lang.reflect.Method.invokeNative(Native Method)
10-14 19:47:34.823 3006-3006/com.webs.mdawdy.htmlspyii E/AndroidRuntime: at java.lang.reflect.Method.invoke(Method.java:515)
10-14 19:47:34.823 3006-3006/com.webs.mdawdy.htmlspyii E/AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
10-14 19:47:34.823 3006-3006/com.webs.mdawdy.htmlspyii E/AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
10-14 19:47:34.823 3006-3006/com.webs.mdawdy.htmlspyii E/AndroidRuntime: at dalvik.system.NativeStart.main(Native Method)