The updateUserSection method is called in a SearchView's OnQueryTextChange. When I type fast into the SearchView, I get a ConcurrentModificationException (it works if I type slowly). I can't tell what causes this problem.
public void updateUserSection(String text){
relevantUsers.clear();
for(String key: allUsers.keySet()) {
if ((key.toLowerCase().contains(text.toLowerCase()))) {
relevantUsers.put(key, allUsers.get(key));
}
}
// instance is a private reference to this AddTrailsAct, probably doesn't matter
instance.generateButtons();
}
private synchronized void generateButtons() {
usersLayout.removeAllViewsInLayout();
// make the first row
currentRow = new LinearLayout(getApplicationContext());
// make it pretty
makePretty(currentRow);
// add the first row
usersLayout.addView(currentRow);
// limits 3 buttons per row
rowIndex = 0;
// iterate through relevantUsers and try to find pictures
(new SetButtonTask(relevantUsers)).execute();
}
private class SetButtonTask extends AsyncTask<Void, Void, Void> {
private HashMap<String, String> userList;
private HashMap<String, Bitmap> nameToBitmap = new HashMap<String, Bitmap>();
public SetButtonTask(HashMap<String, String> userList) {
this.userList = userList;
}
#Override
protected Void doInBackground(Void... v) {
for (String name: userList.keySet()) {
putToBitmap(name, userList.get(name));
}
return null;
}
#Override
protected void onPostExecute(Void v) {
// THE RUNTIME ERROR POINTS TO THE LINE BELOW
for (String name: nameToBitmap.keySet()) {
instance.addToUsersLayout(nameToBitmap.get(name), name);
}
}
private void putToBitmap(String name, String id) {
try {
nameToBitmap.put(name, Bitmap.createScaledBitmap(
BitmapFactory.decodeStream((new URL("https://graph.facebook.com/" +
id +
"/picture?type=large")).openConnection().getInputStream()),
200,
200,
true));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
// add button to the usersLayout
private synchronized void addToUsersLayout(final Bitmap profPicBitmap, final String name) {
runOnUiThread(new Runnable() {
#Override
public void run() {
numTasks++;
Log.d("myTag","the UiThread has " + numTasks + " threads running");
// the button we'll be building
final ImageButton b = new ImageButton(getApplicationContext());
b.setImageBitmap(profPicBitmap);
// touch animation
b.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// set filter when pressed
if (event.getAction() == MotionEvent.ACTION_DOWN) {
b.setColorFilter(new
PorterDuffColorFilter(getResources().getColor(R.color.skyBlue),
PorterDuff.Mode.MULTIPLY));
}
// handle "click"
if (event.getAction() == MotionEvent.ACTION_UP) {
Log.d("myTag", "imageButton pressed");
// add the trail
((Project_18) getApplication()).getMe().addTrail(fb, relevantUsers.get(name));
}
// remove filter on release/cancel
if (event.getAction() == MotionEvent.ACTION_UP ||
event.getAction() == MotionEvent.ACTION_CANCEL) {
b.clearColorFilter();
}
return true;
}
});
// contains button and name of the user
LinearLayout buttonLayout = new LinearLayout(getApplicationContext());
// make button look good and add to buttonLayout
makePretty(b, name, buttonLayout);
// add to buttonMap
buttonMap.put(name, buttonLayout);
// add buttonLayout to row
currentRow.addView(buttonLayout);
// row index handling
if (rowIndex < 2) {
rowIndex ++;
} else {
// reset index
rowIndex = 0;
// make new row
currentRow = new LinearLayout(getApplicationContext());
makePretty(currentRow);
// add new row to the layout
usersLayout.addView(currentRow);
}
numTasks--;
}
});
}
Related
I am making a slot machine app and using kankan's wheel for the same. I want to modify the library such that when the rotation stops the item it will point shoud be the one that I set . I have done this but there is a glitch that shows that we have changed the actual image to the one that we want . How to achieve this?
Update:
I have researched a lot on this and if I am right , android scroll is based on duration and distance not items . From kankan's wheel library I can get current item .Now , I am trying to stop the animation as well as scroll , as soon as a certain duration has been reached and the item is the one that I want (through index) . But this is not working .Please help!!
GameActivity
public class GameActivity extends Activity {
float mDeviceDensity;
String mUuid, mTitle, mContent, mReward;
ImageButton play;
SlotMachineAdapter slotAdapter;
private List<HashMap<String, Object>> slotImages = new ArrayList<HashMap<String, Object>>();
ArrayList<String> imagesWinId = new ArrayList<String>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_filler_up_game);
DisplayMetrics display = getResources().getDisplayMetrics();
mDeviceDensity = display.density;
slotAdapter = new SlotMachineAdapter(this);
getPassedData();
setSoundPlayer(R.raw.clicks,true);
initWheel(R.id.slot_1, false, 0);
initWheel(R.id.slot_2, false, 1);
initWheel(R.id.slot_3, true, 2);
play = (ImageButton) findViewById(R.id.btn_mix);
play.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
shuffle(R.id.slot_1, 5000);
shuffle(R.id.slot_2, 7000);
shuffle(R.id.slot_3, 9000);
}
});
}
protected ImageLoader imageLoader;
ArrayList<SlotItem> arrListSlotItems;
private void getPassedData() {
try {
mUuid = getIntent().getStringExtra(getString(R.string.FILLER_UP_UUID));
imageLoader = ImageLoader.getInstance();
Uuid slotImagesExtra = (Uuid) (getIntent()
.getSerializableExtra(getString(R.string.FILLER_UP_IMAGES)));
arrListSlotItems = slotImagesExtra.getArrSlotItemArray();
for (int i = 0; i < arrListSlotItems.size(); i++)
downloadSlotImages(arrListSlotItems.get(i).getSlotId(), arrListSlotItems.get(i).getImageUrl());
} catch (Exception e) {
e.printStackTrace();
}
}
// Wheel scrolled flag
private boolean wheelScrolled = false;
// Wheel scrolled listener
OnWheelScrollListener scrolledListener = new OnWheelScrollListener() {
public void onScrollingStarted(WheelView wheel) {
wheelScrolled = true;
}
public void onScrollingFinished(WheelView wheel) {
wheelScrolled = false;
setStatus(wheel.getId(), getWheel(wheel.getId()).getWinningIndex());
}
};
// Wheel changed listener
private OnWheelChangedListener changedListener = new OnWheelChangedListener() {
public void onChanged(WheelView wheel, int oldValue, int newValue) {
if (!wheelScrolled) {
}
}
};
/**
* Updates status
*/
private void updateStatus() {
myThread();
}
public void myThread(){
Thread th=new Thread(){
#Override
public void run(){
try
{
Thread.sleep(2000);
GameActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
showAlertDialogWithSingleButton(GameActivity.this, mTitle, mContent, success);
}
});
}catch (InterruptedException e) {
// TODO: handle exception
}
}
};
th.start();
}
android.content.DialogInterface.OnClickListener success = new android.content.DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (mContent != null && mContent.contains("again"))
startHomeActivity();
else
startNewsActivity();
}
};
private void startHomeActivity() {
}
private void startNewsActivity() {
}
android.content.DialogInterface.OnClickListener fail = new android.content.DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//
}
};
public void showAlertDialogWithSingleButton(final Activity ctx, final String title, final String message,
DialogInterface.OnClickListener onClickListener) {
// show dialog
}
private void initWheel(int id, boolean monitorScroll, int itemIndex) {
Random randomGenerator = new Random();
int index = randomGenerator.nextInt(arrListSlotItems.size());
WheelView wheel = getWheel(id);
wheel.setViewAdapter(slotAdapter);
wheel.setCurrentItem((index ));
wheel.setVisibleItems(1);
wheel.setWinningIndex(itemIndex);
wheel.addChangingListener(changedListener);
wheel.addScrollingListener(scrolledListener);
wheel.setCyclic(true);
wheel.setEnabled(false);
}
private WheelView getWheel(int id) {
return (WheelView) findViewById(id);
}
private void setStatus(int id, int item) {
int index = 0;
for (int i = 0; i < arrListSlotItems.size(); i++) {
SlotItem d = arrListSlotItems.get(i);
if (d.getSlotId() != 0 && d.getSlotId() == Integer.parseInt(imagesWinId.get(item)))
index = arrListSlotItems.indexOf(d);
}
getWheel(id).setCurrentItem(index, true);
if (id == R.id.slot_3) {
if(player.isPlaying())
{
stopBackgroundAudio();
}
updateStatus();
}
}
private void shuffle(int id, int duration) {
WheelView wheel = getWheel(id);
wheel.scroll(450 + (int) (Math.random() * 50), duration);
}
private class SlotMachineAdapter extends AbstractWheelAdapter {
final int IMAGE_WIDTH = getImageWidth(mDeviceDensity);
final int IMAGE_HEIGHT = getImageHeight(mDeviceDensity);
private Context context;
/**
* Constructor
*/
public SlotMachineAdapter(Context context) {
this.context = context;
}
/**
* Loads image from resources
*/
private Bitmap loadImage(Bitmap bitmap) {
Bitmap scaled = Bitmap.createScaledBitmap(bitmap, IMAGE_WIDTH, IMAGE_HEIGHT, true);
return scaled;
}
#Override
public int getItemsCount() {
return slotImages.size();
}
// Layout params for image view
final LayoutParams params = new LayoutParams(IMAGE_WIDTH, IMAGE_HEIGHT);
#Override
public View getItem(int index, View cachedView, ViewGroup parent) {
ImageView img;
if (cachedView != null) {
img = (ImageView) cachedView;
} else {
img = new ImageView(context);
}
img.setPadding(0, 5, 0, 5);
img.setLayoutParams(params);
#SuppressWarnings("unchecked")
SoftReference<Bitmap> bitmapRef = (SoftReference<Bitmap>) slotImages.get(index).get("image");
Bitmap bitmap = bitmapRef.get();
if (bitmap == null) {
bitmap = loadImage(bitmap);
}
img.setImageBitmap(bitmap);
return img;
}
}
private int getImageWidth(float density) {
}
private int getImageHeight(float density) {
}
private void downloadSlotImages(final int id, String slotObj) {
//downloading slot images from server
}
}
This is the code. Through this code, when slot stops I want it to scroll some more untill it reaches the image position that I receaved from server. I can do this .But this is providing a lil glitch . Is there any way to stop scrolling when the image is reached as soon as certain duration is reached.
P.S. If you need anymore detail I can provide you.
P.P.S. Screenshots wont give you any detailed insight about the issue.
After days of searching I finally did it.All I had to do was set interpolater as LinearInterpolater and While setting setCurrentItem set animation as true.
This is my class for Print List-view in Android
public class ChatActivity extends FragmentActivity implements OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.act_chat);
listview = (PullToRefreshListView) findViewById(R.id.listView);
editMsg = (EditText) findViewById(R.id.txt_inputText);
mLastSeenTime = (TextView) findViewById(R.id.lastSeenDatetextview);
sendMsgBut = (ImageView) findViewById(R.id.btn_Send);
recciverImage = (ImageView) findViewById(R.id.recciverImage);
backbutton = (ImageView) findViewById(R.id.contact_btnMenu);
sendMsgBut.setOnClickListener(this);
recciverImage.setOnClickListener(this);
backbutton.setOnClickListener(this);
arrChatlist = dbHelper.fetchChatHistory(member_id, reccvierid);
chatList.addAll(arrChatlist);
chatAdapter = new ChatAdapter(this, chatList);
listview.setAdapter(chatAdapter);
listview.setSelection(listview.getAdapter().getCount() - 1);
dbHelper.updateIsRead(reccvierid);
#Override
public void onClick(View arg0) {
switch (arg0.getId()) {
case R.id.btn_Send:
if (TextUtils.isEmpty(editMsg.getText().toString()))
return;
else {
mChatService.SendMessage(Integer.parseInt(member_id), Integer
.parseInt(reccvierid), editMsg.getText().toString());
Chat chat = new Chat();
chat.setMessage(editMsg.getText().toString());
chat.setRecieverID(reccvierid);
chat.setSenderID(member_id);
chatList.add(chat);
dbHelper.addMessage(chat);
chatAdapter.notifyDataSetChanged();
editMsg.setText("");
System.out.println("Messae : " + chat.getMessage());
listview.setSelection(listview.getAdapter().getCount() - 1);
}
break;
default:
break;
}
}
// ****************************** For Location Name *********|||||||
private class SyncStateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
switch (intent.getIntExtra(BroadcastNotifier.EXTENDED_DATA_STATUS,
BroadcastNotifier.STATE_ACTION_COMPLETE)) {
case BroadcastNotifier.STATE_ACTION_MESSAGE_RECEVED:
boolean isCurrentUser = false;
Chat chat = (Chat) intent
.getSerializableExtra(BroadcastNotifier.EXTENDED_CHAT_RECEIVED);
for (Datamodel model : HomeActivity.arrModel) {
if (("~" + model.getPhoneNumber()).equals(chat
.getSenderName())) {
chat.setSenderID(model.getId());
chat.setSenderName(model.getContactName());
}
if (chat.getConnectionId().equals(ConnectionId)) {
isCurrentUser = true;
}
}
if (isCurrentUser) {
dbHelper.addMessage(chat);
chatList.add(chat);
chatAdapter.notifyDataSetChanged();
listview.setSelection(listview.getAdapter().getCount() - 1);
} else {
mChatService.createNotification(chat);
}
break;
}
}
}
//-------- SigNal R Method------------------------\\\
public ChatEventHandler mChatHandler = new ChatEventHandler() {
String previousMessage = "";
#Override
public void UpdateMessage(String message, String sendername,
long senderId) {
if (previousMessage != message) {
System.out.println("new message: " + message + " sendername:"
+ sendername);
Chat chat = new Chat();
chat.setMessage(message);
chat.setRecieverID(member_id);
chat.setSenderID("" + senderId);
chat.setSenderName(sendername);
chat.setIsUnread(false);
dbHelper.addMessage(chat);
chatList.add(chat);
previousMessage = message;
listview.setSelection(listview.getAdapter().getCount() - 1);
}
runOnUiThread(new Runnable() {
#Override
public void run() {
chatAdapter.notifyDataSetChanged();
listview.setSelection(listview.getAdapter().getCount() - 1);
}
});
}
class loadmessge extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
chatAdapter.notifyDataSetChanged();
listview.onRefreshComplete();
super.onPostExecute(result);
}
}
}
This is my XML of listview:
<com.lociiapp.PullToRefreshListView
android:id="#+id/listView"
android:layout_width="match_parent"
android:layout_height="150dp"
android:stackFromBottom="true"
android:transcriptMode="normal" >
I am able to display list-view in Android. Using chatadapter I have applied pull to refresh listview to load data 1 - 1 item in listview after refreshing but its working fine but I want to display that after refresh last item come in last in adapter and first item come in top adapter like tat way but I am unable to do that please see my screen you ll better understand what am trying to do please suggest how I will achieve.
.
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
chatAdapter.notifyDataSetChanged();
// loadPopupData(context, listView, emptyView,i);
listview.setSelection(listview.getAdapter().getCount() - 1);
listview.onRefreshComplete();
super.onPostExecute(result);
}
}
replace this code and Enjoy!!!
Append your chat messages at the end of your list, or implement getItem to return items reversed (length - position).
Looking at your code, I think the first option is the easiest:
public void addMessage(Chat chat) {
values.add(values.size()-1, chat);
this.notifyDataSetChanged();
}
I have a problem with implementing searchview showing its results for data coming from a server. I currently use an AsyncTask so that I don't block the UI. Here's how I implemented it:
searchView.setOnQueryTextListener(new OnQueryTextListener() {
#Override
public boolean onQueryTextChange(String query) {
if (query.length() > 0) {
new GetSearchByNameResultTask(searchView).execute(query);
} else {
return false;
}
return true;
}
#Override
public boolean onQueryTextSubmit(String arg0) {
// TODO Auto-generated method stub
return false;
}
});
GetSearchByNameResultTask
class GetSearchByNameResultTask extends AsyncTask<String, Void, String> {
private SearchView searchView;
public GetSearchByNameResultTask(SearchView searchView) {
this.searchView = searchView;
}
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
return WebRequestHelper.getInfo(params[0]);
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
AppLog.d(TAG, "Result search: " + result);
Gson gson = new Gson();
searchResponseList = gson.fromJson(result, new TypeToken<List<Info>>() {
}.getType());
loadHistory(searchView, searchResponseList);
// TODO: search adapter
}
}
loadHistory() code:
private void loadHistory(SearchView searchView, List<AppInfo> searchResponse) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
searchView.setSuggestionsAdapter(null);
// Cursor
String[] columns = new String[] { "_id", "text" };
Object[] temp = new Object[] { 0, "default" };
MatrixCursor cursor = new MatrixCursor(columns);
final List<Info> items = searchResponse;
for (int i = 0; i < items.size(); i++) {
temp[0] = i;
temp[1] = items.get(i).getName();
cursor.addRow(temp);
}
CursorAdapter ca = new AppListSearchAdapter(this, cursor, items);
new AsyncQueryResult(cursor,ca).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
// SearchView
searchView.refreshDrawableState();
searchView.setSuggestionsAdapter(ca);
searchView.setOnSuggestionListener(new OnSuggestionListener() {
#Override
public boolean onSuggestionSelect(int position) {
// TODO Auto-generated method stub
return false;
}
});
}
}
Problem
Everything runs alright. I'm getting the search results. But I have a problem updating the views. Probably best explained with an example:
Data:
Hell
Hello
Helicopter
text in search: Hel
Result:
Hello World
Hello
Helicopter
text in search: Hell
Hell
Hello
[extra empty space]
the extra empty space is my problem. The "listview" doesn't get updated to fit the results until I type 'Hello'
I forgot to answer this question.
I managed to fix this issue, although it was a bit of a hack on my part. Here's what I did:
#Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
searchAdapter = new SearchAdapter(this, cursor, false);
mSearchView.setSuggestionsAdapter(searchAdapter );
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
searchAdapter.notifyDataSetChanged();
}
}, 200);
//Reload fragment to show list
}
This would force to refresh the search view's adapter. The new Handler().postDelayed() was the key here.
Hope this solution helps.
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();
}