Note that there are some explanatory texts on larger screens.

plurals
  1. POCustom Adapter Listview Android
    primarykey
    data
    text
    <p>I hit my head against the wall, trying to solve this problem for some time. I'm not an experienced Android guy, so its solution might be really simple. That being said, I have the following code:</p> <pre><code> @Override protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.adminusers); super.onCreate(savedInstanceState); // set user_type for Viewall mUserType = 0; lv_adminusersListContent.addFooterView(footerView); mUsersAdapter = new AdminUsersAdapter(mUsersList, AdminUsers.this); lv_adminusersListContent.setAdapter(mUsersAdapter); getUsersList(); } private void getUsersList() { if (UsefulFcts.isOnline(AdminUsers.this)) { if (mThread != null &amp;&amp; mThread.isAlive()) { mThread.interrupt(); } mThread = new Thread() { @Override public void run() { mHandler.post(new Runnable() { @Override public void run() { pDialog = new ProgressDialog(AdminUsers.this); pDialog.setMessage("Loading.. Please wait!"); pDialog.setCancelable(false); pDialog.show(); } }); mUsersList.clear(); mUsersList.addAll(mServiceManager.getUsersList(mUserType, 0 + "", AdminServiceManager.sHowManyToLoad)); mArrayLength = mUsersList.size(); Log.d("arrayLength", String.valueOf(mArrayLength)); Log.d("total_results", String.valueOf(ParserJSON.total_results)); mHandler.post(new Runnable() { @Override public void run() { // refresh listview mUsersAdapter.notifyDataSetChanged(); if (mArrayLength &lt; ParserJSON.total_results) { lv_adminusersListContent .addFooterView(footerView); } else if (mArrayLength &gt;= ParserJSON.total_results) { lv_adminusersListContent .removeFooterView(footerView); } if (0 == mArrayLength) { Toast.makeText(AdminUsers.this, "No username found!", Toast.LENGTH_SHORT).show(); } pDialog.dismiss(); } }); } }; mThread.start(); } else { Toast.makeText(AdminUsers.this, "Internet connection required!", Toast.LENGTH_LONG).show(); } } @Override protected void linkUI() { // begin load_more view footerView = AdminUsers.this.getLayoutInflater().inflate( R.layout.loadmore, null); btn_loadmore = (Button) footerView.findViewById(R.id.btn_loadmore); // end load_more view btn_adminusersViewall = (Button) findViewById(R.id.btn_adminusersViewall); btn_adminusersAdmins = (Button) findViewById(R.id.btn_adminusersAdmins); btn_adminusersClients = (Button) findViewById(R.id.btn_adminusersClients); btn_adminusersDevs = (Button) findViewById(R.id.btn_adminusersDevs); btn_adminAdd = (ImageButton) findViewById(R.id.btn_adminAdd); lv_adminusersListContent = (ListView) findViewById(R.id.lv_adminusersListContent); } @Override protected void setAction() { // begin Buttons UnderHeader btn_adminusersViewall.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { UsefulFcts.setButtonClicked(btn_adminusersViewall, btn_adminusersClients, btn_adminusersAdmins, btn_adminusersDevs); mUserType = 0; mArrayLength = -1; lv_adminusersListContent.removeFooterView(footerView); getUsersList(); } }); btn_adminusersClients.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { UsefulFcts.setButtonClicked(btn_adminusersClients, btn_adminusersDevs, btn_adminusersAdmins, btn_adminusersViewall); mUserType = 1; mArrayLength = -1; // view.setVisibility(View.GONE); getUsersList(); } }); btn_adminusersDevs.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { UsefulFcts.setButtonClicked(btn_adminusersDevs, btn_adminusersClients, btn_adminusersAdmins, btn_adminusersViewall); mUserType = 2; mArrayLength = -1; lv_adminusersListContent.removeFooterView(footerView); getUsersList(); } }); btn_adminusersAdmins.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mUserType = 3; mArrayLength = -1; lv_adminusersListContent.removeFooterView(footerView); getUsersList(); } }); // end Buttons UnderHeader btn_loadmore.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mThread2 = new Thread() { @Override public void run() { mHandler.post(new Runnable() { @Override public void run() { progressBar = new ProgressDialog( AdminUsers.this); progressBar .setMessage("Loading more projects.. "); progressBar.setCancelable(true); progressBar.show(); } }); mUsersList.addAll(mServiceManager.getUsersList( mUserType, String.valueOf(mArrayLength), AdminServiceManager.sHowManyToLoad)); mArrayLength = mUsersList.size(); mHandler.post(new Runnable() { @Override public void run() { mUsersAdapter.notifyDataSetChanged(); if (mArrayLength &gt;= ParserJSON.total_results) { lv_adminusersListContent.removeFooterView(footerView); } progressBar.dismiss(); } }); }; }; mThread2.start(); } }); </code></pre> <p>Note: I basically have a listview which content is requested from a server depending on which button (looking like a tab) I'm pressing (mUserType = 0/1/2/3). I also use a Load More button (footerView = simple layout with a button). Everything seems to work just fine, but after "playing" with the buttons a few times (random number!) it crashes, with the following exception thrown:</p> <pre><code>02-21 11:00:49.252: E/AndroidRuntime(11728): 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(2131296461, class android.widget.ListView) with Adapter(class android.widget.HeaderViewListAdapter)] </code></pre> <p>So, I looked back at the code, but couldn't see any "not on UI thread" listview notification. </p> <p><strong>1.</strong> What could the problem be?</p> <p><strong>2.</strong> Is it necessary to use 2 threads (mThread and mThread2), or could I use the same one, as one's work should start when the other ends (or isn't it ?) and should I declare them static or not ?</p> <p>Also pointing me to any "Good practices" tricks I could use in the future, or "Wrong practices" that I did would be much appreciated!</p> <p>PS. linkUI() and setAction() are called in super().onCreate().</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload