here ia an application where i displaying some text with image background but it got changes position
automatically when notifieddatasetchanged() is called, please help me how to fixed it constant position ,below is my code. thanks you
public View getView(final int position, View convertView, ViewGroup parent) {
//ImageView imageView;
View v;
TextView tv = null;
if (convertView == null) {
LayoutInflater li = getLayoutInflater();
v = li.inflate(R.layout.show_table_gridview, null);
tv = (TextView)
v.findViewById(R.id.tab_num);
tv.setText(""+position+1));
tv.setTextColor(Color.BLACK);
HashMap<Integer, List<OrderlistData>> orederMap1 = ConText
.getTotlaMap();
List<OrderlistData> orderlist1 = new ArrayList<OrderlistData>();
Set<Integer> keySet1 = orederMap1.keySet();
if (keySet1.contains(position))
orderlist1 = orederMap1.get(position);
if (orderlist1.isEmpty()){
}
else{
tv.setBackgroundColor(Color.CYAN);
}
}
else {
v = convertView;
}
/**
* Code for changing background if data is content
*/
return v;
}
here is the code for updating gridview in every 20sec
//=============Refreshing gridview ==============
private class UpdateGridview extends AsyncTask<Context, Integer, String>
{
#Override
protected String doInBackground(Context... params) {
int i = 0;
while (i < 10) {
try {
Thread.sleep(30000);
Message msg = handler.obtainMessage();
handler.sendMessage(msg);
i++;
} catch (Exception e) {
Log.i("makemachine", e.getMessage());
}
}
return "COMPLETE!";
}
private final Handler handler = new Handler() {
public void handleMessage(Message msg) {
getCurrent_orderlist_StatusFromServer();
gridadapter.notifyDataSetChanged();
System.out
.println("i called notifyDataSetChanged()=======================");
}
};
// -- gets called just before thread begins
#Override
protected void onPreExecute()
{
Log.i( "makemachine", "onPreExecute()" );
super.onPreExecute();
}
#Override
protected void onProgressUpdate(Integer... values)
{
super.onProgressUpdate(values);
}
// -- called if the cancel button is pressed
#Override
protected void onCancelled()
{
super.onCancelled();
Log.i( "makemachine", "onCancelled()" );
}
// -- called as soon as doInBackground method completes
// -- notice that the third param gets passed to this method
#Override
protected void onPostExecute( String result )
{
super.onPostExecute(result);
Log.i( "makemachine", "onPostExecute(): " + result );
}
}
It's happening like this because you are giving the if condition. It's because at the first time only convertview gets assigned. For the second time it's not entering into the if condition.
And you have to execute the codes within the if. So just remove the if condition, it will work properly.
Related
I am working on an Application in Android where I shut down all of my servers. Therefore, I use an ArrayAdapter and a Listview.
In a background process, I iterate over the IP - Addresses and shutdown all of my servers.
Now, I want when iterating over my servers to color each row in the ListView in Green ( means still working on it to shut it down ) or Red as soon as the server is shut down.
I am able to color each row in a different color when extending the ArrayAdapter and then in the getView method coloring them all differently.
But how can I do that when iterating over each row during the background process?
My adapter is being set during the call of my Activity class.
Do I have to put the setAdapter method in my backgroundprocess, too, or something like that?
Here is my code:
protected void onCreate(Bundle savedInstanceState) {
initComponents();
}
private void initComponents() {
model = new SharedPreferenceModel(getBaseContext());
mydb = new DatabaseHelper(this);
array_list = mydb.getAllCotacts();
hostsOnline = new ArrayList<String>();
btnShutdown = findViewById(R.id.btnShutdown);
lv = (ListView) findViewById(R.id.listView);
CustomArrayAdapter custom = new CustomArrayAdapter(this, android.R.layout.simple_list_item_1, array_list);
lv.setAdapter(custom);
}
private void addListeners(final ShutdownServers shutdownServers) {
btnShutdown.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new AsyncTask<Integer, String, Void>() {
#Override
protected Void doInBackground(Integer... params) {
try {
for(int i = 0; i<array_list.size(); i++){
posInArray++;
String host = array_list.get(i);
if(host.equals("192.168.1.1"))
publishProgress("Shutdown " + host);
else
executeRemoteCommand(getBaseContext(), host);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
protected void onProgressUpdate(String... values) {
hostsOnline.add(values[0]);
custom.setNotifyOnChange(true);
custom.notifyDataSetChanged();
}
}.execute(1);
}
});
}
Thanks for your help!
You can use setNotifyOnChange(boolean) method and corresponding add(), remove etc. methods to control list state (adding, removing, changing items). Keep in mind, that changing state of backing array field won't trigger UI changes automatically without that. If you want to control changes manually, you can use notifyDataSetChanged() method of ArrayAdapter.
It's all because ArrayAdapter tries to instantiate views only once and reuse them for different array elements when scrolling down. View's state should be only modified in getView() which normally would be called only once per array element, when it's about to be rendered on screen first time. However, you can force 'redraw' using notifyDataSetChanged() at any time to keep UI state consistent with backing array field.
lv.setBackgroundResource(R.drawable.your file)// from drawable
lv.setBackgroundResource(Color.BLACK)// from color by default
Now I was able to solve the colouring problem. Here is my solution:
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
// Get the current item from ListView
View view = super.getView(position,convertView,parent);
if(notifyCalling==1 && position == getPos()){
Log.d("getView - if - position", String.valueOf(position));
view.setBackgroundColor(Color.GREEN);
}else if(notifyCalling ==1 && position < getPos()){
Log.d("getView - elseif - position", String.valueOf(position));
view.setBackgroundColor(Color.RED);
}else if (position % 2 == 1) {
view.setBackgroundColor(Color.LTGRAY);
} else {
view.setBackgroundColor(Color.WHITE);
}
return view;
}
private void addListeners(final ShutdownServers shutdownServers) {
btnShutdown.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
btnShutdown.setClickable(false);
new AsyncTask<Integer, String, Void>() {
#Override
protected Void doInBackground(Integer... params) {
try {
for(int i = 0; i<array_list.size(); i++){
String host = array_list.get(i);
publishProgress(host);
executeRemoteCommand(getBaseContext(), host);
setIndex(i+1);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
protected void onProgressUpdate(String... values) {
custom.setNotifyOnChange(true);
custom.notifyDataSetChanged(getIndex());
}
}.execute(1);
}
});
}
I have used Chris Banes implementation of pull to refresh list view for my app. The problem is if I set visibility for list view as gone or invisible and make it visible in java code, the list doesn't shows up. On the other hand, if I set its visibility as visible or don't set its visibility, every thing works fine. My requirement is such that I have two list views in the same activity. I have to set the visibility as one will appear first once it get data from server. The other will appear on search function. I had set the visibility for search result's listview as gone in the xml code, and making it visible only once it gets search results. Despite using setVisibility() for this listview, it never shows up screen. I had checked server response as well. It is showing search result on logcat.
I am posting my code below:
Code Snippet from Activity
//The result from this async task will populate the first list view
if(NetworkConnection.isOnline(MainCategory.this))
{
new MainMenuAsyncTask(dataUrl, MainCategory.this, listMainMenu, false).execute();
}
else
{
Log.v(TAG, "no network available");
SeattleNightLifeUtility.OpenWiFiDialog(MainCategory.this, getResources().getString(R.string.no_internet_msg));
}
loadListView();
//This will populate the list view that I have created for search results
_txtAutoSearch.setOnEditorActionListener(new TextView.OnEditorActionListener()
{
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event)
{
String term = _txtAutoSearch.getText().toString().trim();
if(! term.equals(""))
{
SeattleNightLifeUtility.hideSoftKeyboard(MainCategory.this, _txtAutoSearch);
if(NetworkConnection.isOnline(MainCategory.this))
{
search(term, false);
}
else
{
SeattleNightLifeUtility.OpenWiFiDialog(MainCategory.this, getResources().getString(R.string.no_internet_msg));
}
}
return true;
}//onEditorAction
});
listMainMenu.setOnRefreshListener(new PullToRefreshListView.OnRefreshListener()
{
#Override
public void onRefresh()
{
if(NetworkConnection.isOnline(MainCategory.this))
{
new MainMenuAsyncTask(dataUrl, MainCategory.this, listMainMenu, true).execute();
}
else
{
SeattleNightLifeUtility.OpenWiFiDialog(MainCategory.this, getResources().getString(R.string.no_internet_msg));
}
}
});
listViewSearch.setOnRefreshListener(new PullToRefreshListView.OnRefreshListener()
{
public void onRefresh()
{
if(NetworkConnection.isOnline(MainCategory.this))
{
search(_txtAutoSearch.getText().toString().trim(), true);
}
else
{
SeattleNightLifeUtility.OpenWiFiDialog(MainCategory.this, getResources().getString(R.string.no_internet_msg));
}
}
});
Search result Async Task
public class GetSearchAsyncTask extends AsyncTask<Void, Void, String>
{
Context ctx;
ProgressDialog pd;
PullToRefreshListView listViewSearch;
public static final String TAG = "GetSearchAsyncTask";
public static ArrayList<SearchDAO> searchArrayList;
private String term, callingclass;
private TextView txtNoData;
boolean flag;
public GetSearchAsyncTask(String term, Context ctx,
PullToRefreshListView listViewSearch, TextView txtNoData,
String callingclass, boolean flag)
{
this.term = term;
this.ctx = ctx;
this.listViewSearch = listViewSearch;
this.txtNoData = txtNoData;
this.callingclass = callingclass;
this.flag = flag;
}//Constructor
#Override
protected void onPreExecute()
{
if(flag == false)
{
pd = new ProgressDialog(ctx);
pd.setMessage(ctx.getResources().getString(R.string.please_wait));
pd.show();
}
}//onPreExecute
protected String doInBackground(Void... params)
{
String parsed = ServerConnection.getSearchedData(term);
try
{
if(flag == true)
{
Log.v(TAG, "doInBackground isListRefreshed is true");
Thread.sleep(2000);
}
}
catch(Exception e){}
return parsed;
}//doInBackground
#Override
protected void onPostExecute(String result)
{
searchArrayList = ParsedSearchData.getSearchedData(result);
listViewSearch.setVisibility(View.VISIBLE);
if(searchArrayList != null && searchArrayList.size() > 0)
{
Log.v(TAG, "searcharraylist not null");
for(int i = 0; i < searchArrayList.size(); i++)
{
Log.v(TAG, "Name: "+searchArrayList.get(i).getMerchant());
}
SearchAdapter mSearchAdapter = new SearchAdapter(ctx, searchArrayList);
mSearchAdapter.notifyDataSetChanged();
listViewSearch.setAdapter(mSearchAdapter);
if(callingclass.equals("EventActivity"))
{
Log.v(TAG, "callingclass EventActivity");
if(txtNoData.getVisibility() == View.VISIBLE)
{
Log.v(TAG, "txtNoData VISIBLE");
txtNoData.setVisibility(View.GONE);
}
if(((EventsActivity)ctx).txtNoEvent.getVisibility() == View.VISIBLE)
{
Log.v(TAG, "txtNoEvent VISIBLE");
((EventsActivity)ctx).txtNoEvent.setVisibility(View.GONE);
}
}
else
{
Log.v(TAG, "callingclass not EventActivity");
if(txtNoData.getVisibility() == View.VISIBLE)
{
Log.v(TAG, "else loop txtNoData VISIBLE");
txtNoData.setVisibility(View.GONE);
}
if(listViewSearch.getVisibility() == View.VISIBLE)
{
Log.v(TAG, "listViewSearch VISIBLE");
}
else
{
Log.v(TAG, "listViewSearch INVISIBLE");
}
}
}
else
{
Log.v(TAG, "searcharraylist null");
if(callingclass.equals("EventActivity"))
{
Log.v(TAG, "callingclass EventActivity");
txtNoData.setVisibility(View.VISIBLE);
listViewSearch.setVisibility(View.GONE);
if(((EventsActivity)ctx).txtNoEvent.getVisibility() == View.VISIBLE)
{
Log.v(TAG, "searcharraylist null else txtNoEvent VISIBLE");
((EventsActivity)ctx).txtNoEvent.setVisibility(View.GONE);
}
}
else
{
Log.v(TAG, "callingclass not EventActivitysearcharraylist null else txtNoEvent VISIBLE");
txtNoData.setVisibility(View.VISIBLE);
listViewSearch.setVisibility(View.GONE);
}
}
if(flag == false)
{
if(pd != null)
{
Log.v(TAG, "onPostExecute pd not null");
if(pd.isShowing())
{
Log.v(TAG, "onPostExecute pd is showing");
pd.dismiss();
}
}
}
else
{
listViewSearch.onRefreshComplete();
}
}//onPostExecute
}
Search Method
protected void search(String term, boolean result)
{
listMainMenu.setVisibility(View.GONE);
//listViewSearch.setVisibility(View.VISIBLE);
new GetSearchAsyncTask(term, MainCategory.this, listViewSearch , txtNoData, "MainCategory", result).execute();
}//search
Earlier I was setting visibility of in the XML as gone and in java code, I was making it VISIBLE. At that time, the list didn't showed up. When I removed the visibility attribute from XML layout file, and only set it in java code with setVisibility(), it worked perfect. I couldn't figured out the reason behind this. May be, I need to take a look at the implementation of library so that I find where did I went wrong. But, for the time being, this is what worked for me.
Sometimes I receive this error on my Activity below, sometimes not:
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.
but I'm not sure where my mistake on my class below. Does anybody have idea?
public class FavoriteActivity extends SpeakSuperActivity {
private final static String TAG = FavoriteActivity.class.getSimpleName();
private Button btn_filter_topic, btn_filter_rating, btn_filter_none;
private TextView fav_filter_text;
private static ListView listViewFavorites;
private static TextView txtNoFavoritesYet;
private List<Favorite> currentFavorites;
private ArrayAdapter<Favorite> currentFavoritesArrayAdapter;
// required for list loading piece by piece
final int itemsPerLoading = Configuration.LOADED_ITEMS_ON_LIST_AT_ONCE;
boolean loadingMore = false;
private List<Long> idList;
int currentDataLoaded;
private static int oldBtnViewId = 0;
// set the start value as same as the loading value
int maximumDataLoadedYet = Configuration.LOADED_ITEMS_ON_LIST_AT_ONCE;
// 0 = not sorted, 1 = sorted by topic and minimum number of stars
private int caseSelection = 0;
private static View progressView;
private View footerView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.favorites);
Log.d(TAG, "FavoritesScreen onCreate()...");
// indicator for waiting processes
progressView = UIUtils.addBlockingProgressIndicatorBlack(this);
// init Listview
listViewFavorites = (ListView) findViewById(R.id.fav_listview_favorites);
// add the footer before adding the adapter, else the footer
// will not load!
footerView = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.listviewfooter, null, false);
listViewFavorites.addFooterView(footerView);
listViewFavorites = (ListView) findViewById(R.id.fav_listview_favorites);
fav_filter_text = (TextView) findViewById(R.id.fav_filter_text);
btn_filter_none = (Button) findViewById(R.id.btn_fav_filter_none);
btn_filter_topic = (Button) findViewById(R.id.btn_fav_filter_topic);
btn_filter_rating = (Button) findViewById(R.id.btn_fav_filter_rating);
toggleButtonStates(R.id.btn_fav_filter_none);
LoadDataTask ldTask = new LoadDataTask();
ldTask.execute();
// no favorites yet?
txtNoFavoritesYet = (TextView) findViewById(R.id.fav_no_favorites_yet);
updateUI();
}
/**
* An asynchronous Task (doesn't block the UI Thread) for loading the Data in background.
*
* #author Jonas Soukup
*/
private class LoadDataTask extends AsyncTask<Void, Void, LoudmouthException> {
private final String TAG = LoadDataTask.class.getName();
protected void onPreExecute() {
super.onPreExecute();
if (FavoriteProvider.getInstance().getNumOfFavorites() != 0)
progressView.setVisibility(View.VISIBLE);
else
progressView.setVisibility(View.GONE);
listViewFavorites.setVisibility(View.GONE);
fav_filter_text.setVisibility(View.GONE);
btn_filter_none.setVisibility(View.GONE);
btn_filter_topic.setVisibility(View.GONE);
btn_filter_rating.setVisibility(View.GONE);
}
protected LoudmouthException doInBackground(Void... params) {
LoudmouthException exception = null;
Log.d(TAG, "loading data..");
switch (caseSelection) {
case 0:
// Get FavoriteList without sorting
idList = FavoriteProvider.getInstance().getFavoritesByDate();
break;
case 1:
// Get FavoriteList sorted by
// Topics + amount of stars
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
float minRating = prefs.getFloat(getResources().getString(R.string.rating_filter_star_amount), 0);
idList = FavoriteProvider.getInstance().getFavoritesByTopicAndMinRating(minRating);
break;
default:
Log.e(TAG, "No Case with number: " + caseSelection);
}
// reset data loaded, so it loads till maximumDataLoadedYet on a
// refresh of the list
currentDataLoaded = 0;
// reset List on Data change
currentFavorites = new ArrayList<Favorite>();
Log.d(TAG, "..loading data finished");
return exception;
}
protected void onPostExecute(LoudmouthException result) {
try {
Log.d(TAG, "LoadDataTask.onPostExecute()");
super.onPostExecute(result);
progressView.setVisibility(View.GONE);
if (result != null) {
// Error ocurred during loading
android.content.DialogInterface.OnClickListener retryClickListener = new android.content.DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
new LoadDataTask().execute();
}
};
UIUtils.showRetryCancelAlertDialog(getApplicationContext(), result, retryClickListener, null);
} else {
// Everythings fine, data loaded
// showing & hiding
if (FavoriteProvider.getInstance().getNumOfFavorites() == 0) {
fav_filter_text.setVisibility(View.GONE);
btn_filter_none.setVisibility(View.GONE);
btn_filter_topic.setVisibility(View.GONE);
btn_filter_rating.setVisibility(View.GONE);
} else {
fav_filter_text.setVisibility(View.VISIBLE);
btn_filter_none.setVisibility(View.VISIBLE);
btn_filter_topic.setVisibility(View.VISIBLE);
btn_filter_rating.setVisibility(View.VISIBLE);
}
if (idList.size() == 0) {
txtNoFavoritesYet.setVisibility(View.VISIBLE);
listViewFavorites.setVisibility(View.GONE);
} else {
txtNoFavoritesYet.setVisibility(View.GONE);
listViewFavorites.setVisibility(View.VISIBLE);
runOnUiThread(new Runnable() {
public void run() {
btn_filter_none.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
caseSelection = 0;
FavoriteProvider.getInstance().setCurrentFavoriteListStateDirty(true);
toggleButtonStates(v.getId());
updateUI();
}
});
btn_filter_topic.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
caseSelection = 1;
TopicFilterFavDialog tfFavDialog = new TopicFilterFavDialog(FavoriteActivity.this, FavoriteActivity.this, v
.getId());
tfFavDialog.show();
}
});
btn_filter_rating.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
caseSelection = 1;
RatingFilterFavDialog ratDialog = new RatingFilterFavDialog(FavoriteActivity.this, FavoriteActivity.this, v
.getId());
ratDialog.show();
}
});
}
});
}
}
// init listview displaying with data loaded step by step
currentFavoritesArrayAdapter = new FavoriteArrayAdapter(FavoriteActivity.this, FavoriteActivity.this, R.layout.favorite_list_entry,
currentFavorites);
listViewFavorites.setAdapter(currentFavoritesArrayAdapter);
currentFavoritesArrayAdapter.notifyDataSetChanged();
} catch (Exception exception) {
// silent catch because activity could be closed meanwhile
Log.i(TAG, "silent exception catch in onPostExecute: " + exception.getMessage());
}
}
}
/**
* Update UI
*/
public void updateUI() {
LoadDataTask ldTask = new LoadDataTask();
ldTask.execute();
if (currentFavoritesArrayAdapter != null)
currentFavoritesArrayAdapter.notifyDataSetChanged();
}
#Override
protected void onResume() {
super.onResume();
updateUI();
}
private class ListMoreItemsTask extends AsyncTask<Void, Void, LoudmouthException> {
#Override
protected LoudmouthException doInBackground(Void... arg0) {
LoudmouthException exception = null;
loadingMore = true;
// reset loading values if adapter was reseted
if (currentFavoritesArrayAdapter.getCount() == 0)
maximumDataLoadedYet = Configuration.LOADED_ITEMS_ON_LIST_AT_ONCE;
// Get value of Configuration.LOADEDITEMSONLISTATONCE new listitems
for (; currentDataLoaded < maximumDataLoadedYet && currentDataLoaded < idList.size(); currentDataLoaded++) {
// Fill the list with new information
currentFavorites.add(FavoriteProvider.getInstance().getFavorite(idList.get(currentDataLoaded)));
}
maximumDataLoadedYet += itemsPerLoading;
// Done loading more.
loadingMore = false;
return exception;
}
protected void onPostExecute(LoudmouthException result) {
if (result == null) {
// Tell to the adapter that changes have been made, this will
// cause
// the list to refresh
currentFavoritesArrayAdapter.notifyDataSetChanged();
// remove loading view when maximum data is reached
if (currentFavorites.size() == idList.size()) {
listViewFavorites.removeFooterView(footerView);
}
}
}
}
public void toggleButtonStates(int viewId) {
// set clicked button as selected
if (viewId != 0) {
switch (viewId) {
case R.id.btn_fav_filter_none:
btn_filter_none.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(R.drawable.filter_neuste_selected), null, null,
null);
btn_filter_none.setTextColor(getResources().getColor(color.black));
break;
case R.id.btn_fav_filter_topic:
btn_filter_topic.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(R.drawable.filter_themen_selected), null, null,
null);
btn_filter_topic.setTextColor(getResources().getColor(color.black));
break;
case R.id.btn_fav_filter_rating:
btn_filter_rating.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(R.drawable.filter_rating_selected), null, null,
null);
btn_filter_rating.setTextColor(getResources().getColor(color.black));
break;
default:
Log.d("TAG", "No View with id: " + viewId);
}
}
// if previews Button exists and wasn't the same button set the old
// one
// to selected false
if (oldBtnViewId != 0 && oldBtnViewId != viewId) {
// set clicked button as not selected
switch (oldBtnViewId) {
case R.id.btn_fav_filter_none:
btn_filter_none.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(R.drawable.filter_neuste), null, null, null);
btn_filter_none.setTextColor(getResources().getColor(R.color.font_grey));
break;
case R.id.btn_fav_filter_topic:
btn_filter_topic.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(R.drawable.filter_themen), null, null, null);
btn_filter_topic.setTextColor(getResources().getColor(R.color.font_grey));
break;
case R.id.btn_fav_filter_rating:
btn_filter_rating.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(R.drawable.filter_rating), null, null, null);
btn_filter_rating.setTextColor(getResources().getColor(R.color.font_grey));
break;
default:
Log.d("TAG", "No View with id: " + viewId);
}
}
oldBtnViewId = viewId;
}
}
It fails because you modify currentFavorite in ListMoreItemsTasks, which is the underlying list that backs your adapter.
The modification is made in doInBackground, which is not the UI Thread.
I would recommend using publishProgress to receive the data to add on the UI Thread and add it to the adapter there (via the adapter's method, not the array, which you should probably not keep after having created the adapter)
edit
Replace
private class ListMoreItemsTask extends AsyncTask<Void, Void, LoudmouthException> {
with
private class ListMoreItemsTask extends AsyncTask<Void, Favorite, LoudmouthException> {
so progresses are Favorite elements, then
currentFavorites.add(FavoriteProvider.getInstance().getFavorite(idList.get(currentDataLoaded)));
with
publishProgress(FavoriteProvider.getInstance().getFavorite(idList.get(currentDataLoaded));
plus insert in the AsyncTask the onProgressUpdate :
onProgressUpdate(Favorite... values) {
currentFavorites.add(values[0]);
currentFavoritesArrayAdapter.notifyDataSetChanged();
}
I have spent many hours looking for a solution to this and need help.
I have a nested AsyncTask in my Android app Activity and I would like to allow the user to rotate his phone during it's processing without starting a new AsyncTask. I tried to use onRetainNonConfigurationInstance() and getLastNonConfigurationInstance().
I am able to retain the task; however after rotation it does not save the result from onPostExecute() to the outer class variable. Of course, I tried getters and setters. When I dump the variable in onPostExecute, that it is OK. But when I try to access to the variable from onClick listener then it is null.
Maybe the code will make the problem clear for you.
public class MainActivity extends BaseActivity {
private String possibleResults = null;
private Object task = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.task = getLastNonConfigurationInstance();
setContentView(R.layout.menu);
if ((savedInstanceState != null)
&& (savedInstanceState.containsKey("possibleResults"))) {
this.possibleResults = savedInstanceState
.getString("possibleResults");
}
if (this.possibleResults == null) {
if (this.task != null) {
if (this.task instanceof PossibleResultWebService) {
((PossibleResultWebService) this.task).attach();
}
} else {
this.task = new PossibleResultWebService();
((PossibleResultWebService) this.task).execute(this.matchToken);
}
}
Button button;
button = (Button) findViewById(R.id.menu_resultButton);
button.setOnClickListener(resultListener);
}
#Override
protected void onResume() {
super.onResume();
}
OnClickListener resultListener = new OnClickListener() {
#Override
public void onClick(View v) {
Spinner s = (Spinner) findViewById(R.id.menu_heatSpinner);
int heatNo = s.getSelectedItemPosition() + 1;
Intent myIntent = new Intent(MainActivity.this,
ResultActivity.class);
myIntent.putExtra("matchToken", MainActivity.this.matchToken);
myIntent.putExtra("heatNo", String.valueOf(heatNo));
myIntent.putExtra("possibleResults",
MainActivity.this.possibleResults);
MainActivity.this.startActivityForResult(myIntent, ADD_RESULT);
}
};
private class PossibleResultWebService extends AsyncTask<String, Integer, Integer> {
private ProgressDialog pd;
private InputStream is;
private boolean finished = false;
private String possibleResults = null;
public boolean isFinished() {
return finished;
}
public String getPossibleResults() {
return possibleResults;
}
#Override
protected Integer doInBackground(String... params) {
// quite long code
}
public void attach() {
if (this.finished == false) {
pd = ProgressDialog.show(MainActivity.this, "Please wait...",
"Loading data...", true, false);
}
}
public void detach() {
pd.dismiss();
}
#Override
protected void onPreExecute() {
pd = ProgressDialog.show(MainActivity.this, "Please wait...",
"Loading data...", true, false);
}
#Override
protected void onPostExecute(Integer result) {
possibleResults = convertStreamToString(is);
MainActivity.this.possibleResults = possibleResults;
pd.dismiss();
this.finished = true;
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (this.possibleResults != null) {
outState.putString("possibleResults", this.possibleResults);
}
}
#Override
public Object onRetainNonConfigurationInstance() {
if (this.task instanceof PossibleResultWebService) {
((PossibleResultWebService) this.task).detach();
}
return (this.task);
}
}
It is because you are creating the OnClickListener each time you instantiate the Activity (so each time you are getting a fresh, new, OuterClass.this reference), however you are saving the AsyncTask between Activity instantiations and keeping a reference to the first instantiated Activity in it by referencing OuterClass.this.
For an example of how to do this right, please see https://github.com/commonsguy/cw-android/tree/master/Rotation/RotationAsync/
You will see he has an attach() and detach() method in his RotationAwareTask to solve this problem.
To confirm that the OuterClass.this reference inside the AsyncTask will always point to the first instantiated Activity if you keep it between screen orientation changes (using onRetainNonConfigurationInstance) then you can use a static counter that gets incremented each time by the default constructor and keep an instance level variable that gets set to the count on each creation, then print that.
I put the code in onResume() method for it to run each time when i load it again by tab click but problem is now that data load first time from server in to list view when I click first time on tab and when I change the tab and load it again it force close and gives "array index out of bound exception". I think it is because it not removes previous loaded data and so how to remove or reload new data on tab click so that exception not occur? This means before loading new data via onResume() how to delete old data?
protected void onPause() {
super.onPause();
}
protected void onResume()
{
super.onResume();
**new ProgressTask6().execute();**
}
private class ProgressTask6 extends AsyncTask<String, Void, Boolean> {
private ProgressDialog dialog;
private Context context;
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(OpeningToday.this);
dialog.setMessage("Processing...");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
#Override
protected void onPostExecute(final Boolean success) {
if (dialog.isShowing())
{
dialog.dismiss();
setListAdapter(new MyAdapter(OpeningToday.this));
}
}
#Override
protected Boolean doInBackground(String... args) {
try{
} catch (Exception e){
Log.e("tag", "error", e);
return false;
}
return null;
}
class MyAdapter extends BaseAdapter implements OnClickListener
{
}
#Override
public int getCount() {
} }
/* Not implemented but not really needed */
#Override
public Object getItem(int position) {
return null;
}
/* Not implemented but not really needed */
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View ConvertView, ViewGroup parent)
{
View v = inflater.inflate(R.layout.listitem_layout, parent, false);
// Log.i("array galoijewdh..",keywordresulttab.array_galleryname[position]);
Log.i("saurabh trivedi","saurabh trivedui");
// Variables.a=3;
String gallerynames = keywordresulttab.array_galleryname[position];
String addresses = keywordresulttab.array_address[position];
TextView tv = (TextView) v.findViewById(R.id.barrio);
tv.setText(gallerynames);
tv = (TextView) v.findViewById(R.id.ciudad);
tv.setText(addresses);
((BaseAdapter)(getListAdapter())).notifyDataSetChanged();
return v;
}
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
}
}
Initialize the index / delete data in onPause() which is the opposite of onResume().
As a rule of thumb (according to activity lifecycle) - clean what you need in the opposite method -
onCreate() - onDestroy()
onStart() / onRestart() - onStop()
onResume() - onPause()