I am trying to update my listview to make an "endless scroll". What happens is that the first 40 results load fine, when i get to the bottom of the scroll, next 40 results replace the first 40...
What I want is for second set of 40 results to add to the first 40 so I have an endless list and ability to scroll back to the beginning of the list.
I am posting my code below. Thank you!
public class SearchResults extends Activity implements BannerAdListener, OnScrollListener{
private LinearLayout bottomNav;
private ListView ringtoneList;
private int start = 0, num = 40, curPage = 1;
private Handler handler = new Handler();
private ProgressDialog progressDialog = null;
private ArrayList<Ringtone> ringtones;
private MoPubView moPubView;
private String searchString;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle extras = getIntent().getExtras();
if (extras == null) {
// no search string defined
finish();
} else {
searchString = extras.getString("search_string");
}
setContentView(R.layout.search_results);
ringtoneList = (ListView)findViewById(R.id.ringtone_list);
ringtoneList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> av, View view, int position, long id) {
Intent i = new Intent(SearchResults.this, RingtoneView.class);
i.putExtra("ringtone", ringtones.get(position));
startActivity(i);
}
});
performSearch();
moPubView = (MoPubView) findViewById(R.id.adview);
moPubView.setAdUnitId(Utils.MoPubBannerId);
moPubView.loadAd();
moPubView.setBannerAdListener(this);
ringtoneList.setOnScrollListener(this);
}
public void onScroll(AbsListView view, int firstVisible, final int visibleCount, int totalCount) {
Log.i("List", "firstVisible="+firstVisible+" visibleCount="+visibleCount+" totalCount="+totalCount);
boolean loadMore = firstVisible + visibleCount >= totalCount;
if(loadMore) {
Log.i("List", "Loading More Results");
curPage++;
start = num * (curPage-1);
new Thread() {
public void run() {
ringtones = Utils.search(start, num, searchString);
if (ringtones != null && ringtones.size() > 0) {
handler.post(new Runnable() {
public void run() {
ringtoneList.setAdapter(new RingtoneRowAdapter(SearchResults.this, ringtones));
}
});
} else {
handler.post(new Runnable() {
public void run() {
new AlertDialog.Builder(SearchResults.this)
.setTitle(getResources().getString(R.string.context_info)).setMessage(getResources().getString(R.string.context_noresult))
.setPositiveButton(getResources().getString(R.string.context_ok), null).show();
}
});
}
}
}
.start();
}
}
public void onScrollStateChanged(AbsListView v, int s) { }
private void performSearch() {
progressDialog = ProgressDialog.show(SearchResults.this, getResources().getString(R.string.loading_message), getResources().getString(R.string.loading_search), true);
new Thread() {
public void run() {
ringtones = Utils.search(start, num, searchString);
if (ringtones != null && ringtones.size() > 0) {
updateList();
} else {
handler.post(new Runnable() {
public void run() {
new AlertDialog.Builder(SearchResults.this)
.setTitle(getResources().getString(R.string.context_info)).setMessage(getResources().getString(R.string.context_noresult))
.setPositiveButton(getResources().getString(R.string.context_ok), null).show();
ringtoneList.setVisibility(View.INVISIBLE);
bottomNav.setVisibility(View.INVISIBLE);
}
});
}
progressDialog.dismiss();
}
}.start();
}
private void updateList() {
handler.post(new Runnable() {
public void run() {
//Log.d("search", "ringtones.size() " + ringtones.size());
ringtoneList.setVisibility(View.VISIBLE);
ringtoneList.setAdapter(new RingtoneRowAdapter(SearchResults.this, ringtones));
}
});
}
}
Please help! Thank you!
While I can't be 100% sure, I think your problem has to do with the fact that you're setting a new adapter that only has the section of ringtones that in loads. It probably has to do with this snippet:
ringtones = Utils.search(start, num, searchString);
if (ringtones != null && ringtones.size() > 0) {
handler.post(new Runnable() {
public void run() {
ringtoneList.setAdapter(new RingtoneRowAdapter(SearchResults.this, ringtones));
}
});
}
Instead of putting an entirely new array of ringtones, you should add on to the one you already have. Your ringtones variable is already an instance variable, so I'm sure if you changed this line:
ringtones = Utils.search(start, num, searchString);
to the following:
ringtones.addAll(Utils.search(start, num, searchString));
It might fix your problem.
Your code is a little bit messy, but your updateList method is creating a NEW RingtoneRowAdapter. You should ADD items to the list and call
mRingtoneRowAdapter.notifyDatasetChanged();
That will tell the adapter to get new views (if needed) along with a lot of internal stuff happening at Adapter's level. So it's kinda:
private void updateList() {
handler.post(new Runnable() {
public void run() {
if ( mAdapter == null ) {
mAdapter = new RingtoneRowAdapter(SearchResults.this, ringtones);
ringtoneList.setAdapter(mAdapter);
} else {
mAdapter.notifyDataSetChanged();
}
ringtoneList.setVisibility(View.VISIBLE);
}
});
}
And of course, as already suggested, don't init your ringtones array all the time. Just add data to it.
You don't need (most of the times) to hide the list, you can add in your layout, any View (including a full Layout!) with an id of:
android:id="#android:id/empty"
And if your ListView has an id of android:id="#id/android:list", and you're in a ListFragment or ListActivity, then when the list is empty, the "empty" layout will be shown (which can be a dummy view if you don't want to see it).
Just suggestions :)
UPDATE: For your null, I see that the logic is a little bit weird and since we don't know the requirements for your app (i.e. what to do if there are no results, what to do if the results are invalid, etc.) I'll assume you just want to make sure it works and deal with that later.
So with that in mind, I see two problems.
I assume your Utils.search method can return null, because you're checking for it. To me that feels strange, I'd rather return an empty array indicating that the search produced no results; that little remark aside, you are not checking (or we don't know because we haven't seen the source for your search method), if the searchString is null or not.
You haven't provided a stack trace, so we can't tell where the null is happening (either inside search or ?)
A quick solution would be to check for null before searching… I would personally do this INSIDE the search function.
Something like:
public ArrayList<Ringtone> search(final int start, final int num, final String searchString) {
if ( searchString == null ) {
//DECIDE WHAT YOU WANT TO DO, EITHER:
return null;
// OR YOU CAN RETURN AN EMPTY ARRAY
return new ArrayList<Ringtone>();
}
// You should check for these (change according to your rules)
if (start < 0 ) {
start = 0; // protect yourself from bad data.
}
if ( num < 0 ) {
num = 0;
}
/// THE REST OF YOUR search FUNCTION
return <your array>
}
Now another thing is that you may want the search to return incremental results (so you can ADD them to your array (instead of returning a new array every time). For that, as already suggested, use the addAll trick, but then, DON'T return null, return an new empty array, so there's no harm done if there's nothing else to add.
Related
I have a problem with showing progress on ProgressBar.
I have function that calls my server with Volley, when return result I have implemented a Callback that return data to my activity.
Something like:
public static void saveData(Data data, final VolleyCallbackJsonObject callback){
...
callback.onSuccessResponse(new JSONObject());
...
}
Supposing that the function is called on cycle like:
for(int i = 1; i<=5; i++){
final int copyIndex = i;
MyClass.saveData(new Data(i), new VolleyCallbackJsonObject() {
#Override
public void onSuccessResponse(JSONObject result) {
callFunctionForShowAndUpdateProgress(copyIndex);
}
})
}
}
I would like show a ProgressBar that show a bar with a progress from 1/5 to 5/5
so I have my Function in my activityClass:
public Class Test extends Activity{
private ProgressBar pb;
public void callFunctionForShowAndUpdateProgress(int index){
if(index == 1){
pb = (ProgressBar) findViewById(R.id.pbLoading);
pb.setMax(5);
pb.setIndeterminate(false);
pb.setVisibility(View.VISIBLE);
}
if(pb != null){
pb.setProgress(index);
}
if(index == 5){
pb.postDelayed(new Runnable() {
#Override
public void run() {
pb.setVisibility(View.GONE);
}
}, 3000);
}
}
}
My problem is that progress bar not set progress, but it show only at the end so with 5/5 and not show the progress step (1/5, 2/5, 3/5, 4/5) and then it will hide after 3 seconds how specified on postDelayed.
So How can I show all the step? what is wrong?
Try to postDelay the method 'callFunctionForShowAndUpdateProgress' in the method 'onSuccessResponse' instead the postDelay you are already making because the delay you are making happens only when i = 5, so technically the progress goes through 2, 3, and 4 but you don't see it.
try this inside 'onSuccessResponse':
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
callFunctionForShowAndUpdateProgress(copyIndex);
}
}, 3000);
By the way, When the method 'callFunctionForShowAndUpdateProgress' is called in the
'onSuccessResponse' the index initially will be 1 and that is fine, the compiler then will go to second if statement
if(pb != null){
pb.setProgress(index);
}
and will execute it because the condition is correct there, it will not cause a problem but leaving it like this is not a good practice, to solve this prevent the compiler from getting into this if statement by adding else.
I hope that helps
Change your cycle calling function as like below and then check,
int copyIndex = 1;
callFunctionForShowAndUpdateProgress(copyIndex);
for(int i = 1; i<=5; i++)
{
MyClass.saveData(new Data(i), new VolleyCallbackJsonObject()
{
#Override
public void onSuccessResponse(JSONObject result)
{
copyIndex++;
callFunctionForShowAndUpdateProgress(copyIndex);
}
})
}
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'm looking for a way to speed up the creation of a TableLayout with over 1000 rows. Is there a way to create a TableLayout entirely on a separate thread or a way to speed it up?
Here is my method that is creating the table:
private void setTable()
{
final Activity activity = this;
final Handler handler = new Handler();
new Thread(new Runnable()
{
#Override
public void run()
{
for (int x = 0; x < rooms.size(); x++)
{
final int inx = x;
handler.post(new Runnable()
{
#Override
public void run()
{
Methods.createRow(table, rooms.get(inx), null, activity);
TableRow row = (TableRow)table.getChildAt(inx);
row.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View arg0)
{
if (arg0.getTag() != null && arg0.getTag().getClass() == Integer.class)
select((Integer)arg0.getTag());
}
});
}
});
}
}
}).start();
}
I was hoping that using a Handler would at least allow the new Activity to appear before the table was created. The application seems to freeze up for a few seconds when creating tables with a lot of rows. setTable() is being run in my Activity's onStart() method.
Methods.createRow adds a row to the end of the TableView that is passed in.
Edit:
After deciding to try out a ListView, I got much better results with a lot less code.
private void setTable()
{
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, roomNames);
table.setAdapter(adapter);
table.setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3)
{
select(arg2);
}
});
}
First things first.
Why your app freezes:
Handler works like a queue, it queues every post you made and than execute it serially in your main thread.
But the main problem is the amount of data you are trying to show at once, but it is easily solved with an Adapter, you probably can use some default Component for solve this, like ListView or GridView, you can make your custom rows to work around the columns maybe.
Just from guessing on the method name, it seems this line may be slow to run on the main/UI thread:
Methods.createRow(table, rooms.get(inx), null, activity);
I would suggest separating all the heavy database work and UI work with AsyncTask, so it might look something like this:
private OnClickListener rowClickListener = new OnClickListener()
{
#Override
public void onClick(View arg0)
{
if (arg0.getTag() != null && arg0.getTag().getClass() == Integer.class)
select((Integer)arg0.getTag());
}
};
private void setTable()
{
final Activity activity = this;
final Handler handler = new Handler();
new AsyncTask<Void, Void, List<TableRow>>() {
#Override
protected List<TableRow> doInBackground(Void... params) {
// Do all heavy work here
final List<TableRow> rows = new ArrayList<TableRow>(rooms.size());
for (int x = 0; x < rooms.size(); x++)
{
Methods.createRow(table, rooms.get(x), null, activity);
rows.add((TableRow)table.getChildAt(x));
}
return rows;
}
#Override
protected void onPreExecute() {
// maybe show progress indication
}
#Override
protected void onPostExecute(List<TableRow> result) {
// Do all UI related actions here (maybe hide progress indication)
for (final TableRow row : result) {
row.setOnClickListener(rowClickListener);
}
}
};
}
Since I can't tell what is in some methods, you'll just need to ensure you've tried to optimize as best as possible in Methods.createRow(...) and move all the UI related work to the onPostExecute(...) method.
You are stacking the post with all the actions at once. So it same as not using a thread at all as your main thread doing all the work. Try changing to postDelay, and for each room index give it 1 millisecond or more.
I have an activity whose only purpose is to display a list view. There is a custom adapter to serve up the views for each element in the array.
I have break points all over and when I debug, it stops in "count" a number of times - the first few times the return value is zero, then it changes to 3 (the correct value in this case). Then we stop in "getView" - all the right stuff happens, and after we're through with all the break points, then presto magico all three records display on the screen. Yea!
So then I try to run the app outside of the debugger. I get the log message that it's visited "count", and the log message displays the return value so I know it's correct - but "getView" never gets called!!
I'm not sure which bits of code are relevant to this question & don't want to pollute the question with the entire project; please let me know if there's a specific section that would be helpful. I've researched all the "getView not called" questions but those consistently are for a case where getView never gets called, which clearly mine can be…sometimes :(
EDIT: Adapter code
public class DivisionAdapter extends BaseAdapter {
private static final String TAG = "DIV_ADAPT";
private ArrayList<Division> divisionList;
private Context context;
public DivisionAdapter(Context c, ArrayList<Division> divList) {
divisionList = divList;
context = c;
}
#Override
public int getCount() {
Integer count = 0;
if (divisionList != null) count = divisionList.size();
Log.v(TAG,count.toString());
return count;
}
#Override
public Object getItem(int position) {
Object o = null;
if (divisionList != null)
o = divisionList.get(position);
return o;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.v(TAG,"getView");
if (divisionList == null)
return null;
LinearLayout divisionView = null;
Division thisDiv = divisionList.get(position);
if (convertView == null) {
divisionView = new LinearLayout(context);
LayoutInflater li = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
li.inflate(R.layout.division_item, divisionView, true);
} else {
divisionView = (LinearLayout) convertView;
}
Log.v(TAG,thisDiv.name());
TextView v = (TextView) divisionView.findViewById(R.id.divisionName);
v.setText(thisDiv.name());
v = (TextView) divisionView.findViewById(R.id.divisionRegion);
v.setText(thisDiv.region());
return divisionView;
}
public void setList(ArrayList<Division> newList) {
divisionList = null;
divisionList = newList;
}
}
And just in case it's useful, some snippets from the activity class:
#Override
public void onResume() {
super.onResume();
refreshList();
}
private void refreshList() {
// use the class static query method to get the list of divisions
Division.query(Division.class,
new StackMobQuery().fieldIsEqualTo("status", "ACTIVE"),
new StackMobQueryCallback<Division>() {
#Override
public void failure(StackMobException arg0) {
// TODO Auto-generated method stub
Log.v(TAG, "query fail");
}
#Override
public void success(List<Division> arg0) {
Log.v(TAG, "query success");
divAdapt.setList((ArrayList<Division>) arg0);
divAdapt.notifyDataSetChanged();
}
});
}
EDIT 2/11:
I found this question: Markers not showing on map after stackmob query which reveals the hitherto unknown fact that stack mob queries run on a background thread. I'm starting to research the relationship between threads and adapters and thought I'd share this clue in case it helps anyone else figure out what's going on here faster than I can. TIA.
idk why this EVER worked in the debugger - that turned out to be a red herring.
As discovered, the StackMobModel static query method does run in a background thread, from which calling NotifyDataSetChanged() is completely ineffectual.
I ended up replacing the success method in the StackMobQueryCallback as follows:
#Override
public void success(final List<Division> arg0) {
Log.v(TAG, "query success");
runOnUiThread(new Runnable() {
public void run() {
updateList((ArrayList<Division>) arg0);
}
});
}
and then added this new method
private void updateList(ArrayList<Division> newList) {
divAdapt.setList(newList);
divAdapt.notifyDataSetChanged();
}
now, when the query returns, the adapter update is directed to run on the proper thread, and hooray, everything looks stitched together just fine and dandy.
whew!
I manage an AutoCompleteTextView that should give all the towns (ville) found in my DB, according the 4 first letters I put in.
The Async task works well and gets the right data.
My problem is that the DropDownList display NOT all the items. Often only 1, 2, 3 or 4 out of the 20 returned by the DB.
So I figured out, there should be some auto filtering within the ACTV itself!
I check many topics here on SO, to update my code but I didn't succeed.... :-(
I keep getting errors without knowing exactly what the trouble is! :-(
AutoCompleteTextView force to show all items
AutoCompleteTextView - disable filtering
So here is my code:
class MyActivity extends Activity implements AdapterView.OnItemClickListener
{
static class Ville
{
String id;
String name;
#Override
public String toString() { return this.name; }
};
ArrayAdapter<Ville> villeAdapter;
String villeAdapterFilter;
VilleUpdateTask villeAdapterUpdateTask;
AutoCompleteTextView villeText;
Ville selectedVille;
final TextWatcher textChecker = new TextWatcher() {
public void afterTextChanged(Editable s) {}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int before, int count)
{
MyActivity.this.setAdapterFilter(s.toString());
}
};
public void onCreate(Bundle bundle)
{
super.onCreate(bundle);
setContentView(R.layout.main);
this.villeAdapter = new ArrayAdapter<Ville>(this,android.R.layout.simple_dropdown_item_1line, new Ville[0]);
this.villeText = (AutoCompleteTextView ) findViewById(R.id.villeSelector);
this.villeText.setAdapter(this.villeAdapter);
this.villeText.setThreshold(THRESHOLD_DROPDOWN);
this.villeText.setOnItemClickListener(this);
this.villeText.addTextChangedListener(textChecker);
}
public void onDestroy() { stopVilleAdapterUpdate();
public void setAdapterFilter(String filter)
{
if (filter == null) {
// clearing the adapter
this.villeAdapterFilter = null;
this.villeAdapter.clear();
this.villeAdapter.notifyDataSetChanged();
Log.d("MyActivity","Clearing ville filter !");
} else if (filter.length() > THRESHOLD_QUERY) {
if (this.villeAdapterFilter == null) {
Log.d("MyActivity","Ville Adapter Filter defined to:"+filter);
this.villeAdapterFilter = filter;
startVilleAdapterUpdate();
} else {
Log.d("MyActivity","Already filtered with:"+this.villeAdapterFilter);
}
} else {
Log.d("MyActivity","Resetting filter (not enough data)");
this.villeAdapterFilter = null;
this.villeAdapter.clear();
this.villeAdapter.notifyDataSetChanged();
}
}
public synchronized void onItemClick(ViewAdapter<?> ad, View v, int position, long id)
{
this.selectedVille = this.villeAdapter.getItemAtPosition(position);
Log.d("MyActivity","Ville selected: "+this.selectedVille);
}
public synchronized void startVilleAdapterUpdate()
{
stopVilleAdapterUpdate();
Log.d("MyActivity","Starting Update of Villes with "+this.villeAdapterFilter);
this.villeAdapterUpdateTask = new VilleUpdateTask();
this.villeAdapterUpdateTask.execute(this.villeAdapterFilter);
}
public synchronized void stopVilleAdapterUpdate()
{
if (this.villeAdapterUpdateTask != null) {
Log.d("MyActivity","Stopping current update of villes");
this.villeAdapterUpdateTask.cancel(true);
this.villeAdapterUpdateTask = null;
}
}
public synchronized void onVilleAdapterUpdateResult(Ville[] data)
{
this.villeAdapterUpdateTask = null;
if (data != null) {
Log.d("MyActivity","Received "+data.length+" villes from update task");
this.villeAdapter.clear();
this.villeAdapter.addAll(data);
this.villeAdapter.notifyDataSetChanged(); // mise à jour du drop down...
}
}
class VilleUpdateTask extends AsyncTask<String,Void,Ville[]>
{
public Ville[] doInBackground(String ... filters)
{
ArrayList<Ville> values = new ArrayList<Ville>();
try {
HttpClient httpclient = new DefaultHttpClient();
....
....
for(int i=0;i<json_array.length();i++) {
JSONObject json_ligne = json_array.getJSONObject(i);
try {
Ville v = new Ville();
v.name = json_ligne.getString("NAME_VILLE");
v.id = json_ligne.getString("ID_VILLE");
values.add(v);
} catch (Exception ex) {
Log.w("VilleUpdateTask","Invalid value for Ville at index #"+i,ex);
}
}
} catch (Exception ex) {
Log.e("VilleUpdateTask","Failed to retrieve list of Ville !",ex);
}
return values.toArray(new Ville[values.size()]);
}
public void onPostExecute(Ville[] data)
{
MyActivity.this.onVilleAdapterUpdateResult(data);
}
}
}
EDIT 1: yep sorry, my ACTV is a basic TextView, it is not a scrolling problem because on better case I can see 10 items in the list, and last the position is random
EDIT 2: could you just help me to adapt my existing code to the given solutions from the 2 URLs above?
(1) according to that solution AutoCompleteTextView - disable filtering
I have to:
create my class ClassMyACArrayAdapter which is the same as the given one, only its name changes
change my declaration from
ArrayAdapter villeAdapter;
to
List<ClassMyACArrayAdapter> villeAdapter;
but in the onCreate what should replace the initial
this.villeAdapter = new ArrayAdapter
(this,android.R.layout.simple_dropdown_item_1line, new Ville[0]);
Just call autoCompleteTextView.showDropDown() Whenever you need it.....cheers :)
Is your AutoCompleteTextView a TextView, LinearLayout o ListView? The code in your activity looks fine, so I'm guessing that the problem could be in the layout (maybe you're not using a scroll so you can only see the first values).
Also, the values that you see are always the first ones in the returned list or they're at random positions?