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.
Related
I don't know what happens but my searchView not working well when I input a 2 words value in search bar.
for example:
my listview displayed like this
You save me
Above All
I am not ashamed
In searchbar I want to search the song "You save me" with the keyword of "You". The result was fine and displayed the exact match but when I am trying to input the "You save" keyword the result doesn't appear anything in listview. It seems that searchview doesn't work when the inputted value has space between 2 words.
how can I fix this problem?
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return false;
}
});
try this
searchView.setOnEditorActionListener(new EditText.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
return true;
}
});
addTextChangeListener();
now create this method
private void addTextChangeListener() {
searchView.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence query, int start, int before, int count) {
query = query.toString().trim().toLowerCase();
final ArrayList<CityDataModel> filteredList = new ArrayList<>();
final CharSequence finalQuery = query;
new Thread(new Runnable() {
#Override
public void run() {
// Clear the filter list
filteredList.clear();
// If there is no search value, then add all original list items to filter list
if (TextUtils.isEmpty(finalQuery)) {
filteredList.addAll(cities);
} else {
// Iterate in the original List and add it to filter list...
for (CityDataModel item : cities) {
if (item.getCity_name().toLowerCase().contains(finalQuery.toString().toLowerCase())
) {
// Adding Matched items
filteredList.add(item);
}
}
}
// Set on UI Thread
((Activity) context).runOnUiThread(new Runnable() {
#Override
public void run() {
// Notify the List that the DataSet has changed...
adapter = new SearchCityAdapter(SearchCityClass.this, filteredList);
recyclerSearchCity.setAdapter(adapter);
if (filteredList.size() == 0) {
tvNoCityFound.setVisibility(View.VISIBLE);
} else {
tvNoCityFound.setVisibility(View.GONE);
}
}
});
}
}).start();
}
#Override
public void afterTextChanged(Editable s) {
}
});
}
Okay, guys. This post is very old but seems that no more has interested to answers my question, so I decided to answer my old question in case someone has the same issue as mine.
Very important: Use RecyclerView instead of ListView for better performance.
Create Recyclerview adapter and implement this class Filterable to your adapter.
then add this code.
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
final String text = charSequence.toString().toLowerCase();
List<SongsEntity> list;
if (text.isEmpty()) {
list = entitySongs; //"entitySongs" is your original arraylist
}else {
List<SongsEntity> songlist = new ArrayList<>();
for (SongsEntity song : entitySongs) {
if ((song.getTitle().toLowerCase().trim().contains(text)))
{
songlist.add(new SongsEntity(song.getId(), song.getTitle(), song.getArtist(),song.getLyrics()));
}
}
list = songlist;
}
FilterResults results = new FilterResults();
results.values = list;
return results;
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
songFiltered = (List<SongsEntity>) filterResults.values; // //"songFiltered" is your filtered arraylist
notifyDataSetChanged();
}
};
}
I don't remember the exact cause of that issue but I fixed that issue with this code above.
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();
}
following code, I try update Adapter. Code is properly done .But Mobile to goes Hong mode.After the loop ends. Data is displayed.
(MainActivity.this).runOnUiThread(new Runnable() {
#Override
public void run() {
for(News news : SharedVar.getCurrentNews()){
_adapter.notifyDataSetChanged();
int currentIndex=news.getIndex();
Log.d("SRC_IMAGE_ADDRESS", news.getImageNewsAddress());
News replaceNews=new News();
News oldNews =_adapter.getItem(currentIndex);
replaceNews.setTitle(oldNews.getTitle()+" ( "+String.valueOf(currentIndex)+" )");
replaceNews.setImageNews(Helpers.GetImageFromUrl(news.getImageNewsAddress()));
SharedVar.getCurrentNews().set(currentIndex, replaceNews);
_adapter.notifyDataSetChanged();
}
}
});
Update :
I changed my code like the following code.
Hong mode is still not resolved.How do I fix it?
(MainActivity.this).runOnUiThread(new Runnable() {
#Override
public void run() {
for(News news : SharedVar.getCurrentNews()){
int currentIndex=news.getIndex();
Log.d("SRC_IMAGE_ADDRESS", news.getImageNewsAddress());
News replaceNews=new News();
News oldNews =_adapter.getItem(currentIndex);
replaceNews.setTitle(oldNews.getTitle()+" ( "+String.valueOf(currentIndex)+" )");
replaceNews.setImageNews(Helpers.GetImageFromUrl(news.getImageNewsAddress()));
SharedVar.getCurrentNews().set(currentIndex, replaceNews);
}
_adapter.notifyDataSetChanged();
}
});
Update 2 :
public static Bitmap GetImageFromUrl(String url) {
URL urlForImage;
Bitmap imageNews=null;
try {
urlForImage = new URL(url);
URLConnection conn = urlForImage.openConnection();
imageNews= BitmapFactory.decodeStream(conn.getInputStream());
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return imageNews;
}
Update 3 :
again : I changed my code like the following code. Hong mode is still not resolved.
public class AsyncTaskReadImageNews extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... arg0) {
(MainActivity.this).runOnUiThread(new Runnable() {
#Override
public void run() {
for(News news : SharedVar.getCurrentNews()){
int currentIndex=news.getIndex();
Log.d("INDEX_ITEM", String.valueOf(currentIndex));
News replaceNews=new News();
News oldNews =_adapter.getItem(currentIndex);
replaceNews.setTitle(oldNews.getTitle()+" ( "+String.valueOf(currentIndex)+" )");
replaceNews.setImageNews(Helpers.GetImageFromUrl(news.getImageNewsAddress()));
SharedVar.getCurrentNews().set(currentIndex, replaceNews);
}
}
});
return null;
}
#Override
protected void onPostExecute(Void result) {
_adapter.notifyDataSetChanged();
}
}
}
This is all my code :
public class MainActivity extends Activity {
NewsAdapter _adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
boolean result=true;
int id = item.getItemId();
switch (id) {
case R.id.action_transfer_news:
SharedVar.setCurrentTask(Taskes.GET_TRANSFER_NEWS);
new JsoupCommands().ConnectToWebsite(MainActivity.this);
break;
case R.id.action_settings:
break;
default:
result=super.onOptionsItemSelected(item);
break;
}
return result;
}
public class JsoupCommands {
private Dialog _dialog;
private RatingBar _loadingStar;
public void ConnectToWebsite(Context context) {
_dialog = new Dialog(context);
_dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
_dialog.setContentView(R.layout.loading_layout);
_loadingStar=(RatingBar) _dialog.findViewById(R.id.loading_RatingBar);
Helpers.ConfigRatingLoader(_loadingStar);
new AsyncTaskJsoup().execute();
}
public class AsyncTaskJsoup extends AsyncTask<Void, Void, String>{
boolean _startThread;
Element _NewsRegion;
Elements _links;
List<News> _LisOfNews;
int _step=0;
#Override
protected String doInBackground(Void... listviews) {
String result=null;
Document doc;
try {
threadLoading.start();
SharedVar.clearNews();
doc = Jsoup.connect(Helpers.getCurrentTaskLink()).get();
_NewsRegion = doc.getElementById("content-post");
_links = _NewsRegion.select("article div[class=arch_body]");
_LisOfNews = new ArrayList<News>();
for (Element element : _links) {
Element textNewsElement = element.select("div[class=arch_content] a").first();
Element imageNewsElement = element.select("div[class=arch_img] a img").first();
String imageSrcNews = imageNewsElement.attr("src").trim().replace("../../../..", Helpers.GetCurrentSite());
String titleNews = textNewsElement.text().trim();
String linkNews = textNewsElement.attr("href").trim().replace("../../..", Helpers.GetCurrentSite()+"/persian");
String dateNews=textNewsElement.nextSibling().toString().trim();
News news = new News();
news.setIndex(_LisOfNews.size());
news.setTitle(titleNews);
news.setLink(linkNews);
news.setDate(dateNews);
news.setImageNewsAddress(imageSrcNews);
_LisOfNews.add(news);
}
SharedVar.setCurrentNews(_LisOfNews);
result="Success";
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
Thread threadLoading = new Thread()
{
#Override
public void run() {
try {
while(_startThread) {
Helpers.SetRatingLoad(_loadingStar, _step);
if(_step++==3){
_step=0;
}
Log.d("DELAY", String.valueOf(_step));
sleep(200);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
#Override
protected void onPostExecute(String result) {
_startThread=false;
_dialog.dismiss();
FillNewsinListView();
new AsyncTaskReadImageNews().execute();
}
private void FillNewsinListView() {
List<News> news=SharedVar.getCurrentNews();
if(news!=null&&news.size()>0){
Log.d("FILL_NEWS", "YES");
_adapter = new NewsAdapter(MainActivity.this, R.layout.rows_news, SharedVar.getCurrentNews());
((ListView)findViewById(R.id.news_listView)).setAdapter(_adapter);
}else{
Log.d("FILL_NEWS", "NO");
}
}
#Override
protected void onPreExecute() {
_startThread=true;
_dialog.show();
}
}
public class AsyncTaskReadImageNews extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... arg0) {
(MainActivity.this).runOnUiThread(new Runnable() {
#Override
public void run() {
for(News news : SharedVar.getCurrentNews()){
int currentIndex=news.getIndex();
Log.d("INDEX_ITEM", String.valueOf(currentIndex));
News replaceNews=new News();
News oldNews =_adapter.getItem(currentIndex);
replaceNews.setTitle(oldNews.getTitle()+" ( "+String.valueOf(currentIndex)+" )");
replaceNews.setImageNews(Helpers.GetImageFromUrl(news.getImageNewsAddress()));
SharedVar.getCurrentNews().set(currentIndex, replaceNews);
}
}
});
return null;
}
#Override
protected void onPostExecute(Void result) {
_adapter.notifyDataSetChanged();
}
}
}
}
Your app hangs because you're doing the image downloading on the UI Thread. You'll need to do the image downloading off the UI thread.
What I'd suggest is to create an AsyncTask, add all the processing inside doInBackground() method and the _adapter.notifyDataSetChanged() inside onPostExecute() since this is the only thing that you need to call on the UI Thread.
change this:
(MainActivity.this).runOnUiThread(new Runnable() {
#Override
public void run() {
for(News news : SharedVar.getCurrentNews()){
_adapter.notifyDataSetChanged();
int currentIndex=news.getIndex();
Log.d("SRC_IMAGE_ADDRESS", news.getImageNewsAddress());
News replaceNews=new News();
News oldNews =_adapter.getItem(currentIndex);
replaceNews.setTitle(oldNews.getTitle()+" ( "+String.valueOf(currentIndex)+" )");
replaceNews.setImageNews(Helpers.GetImageFromUrl(news.getImageNewsAddress()));
SharedVar.getCurrentNews().set(currentIndex, replaceNews);
_adapter.notifyDataSetChanged();
}
}
});
to this:
(MainActivity.this).runOnUiThread(new Runnable() {
#Override
public void run() {
for(News news : SharedVar.getCurrentNews()){
int currentIndex=news.getIndex();
Log.d("SRC_IMAGE_ADDRESS", news.getImageNewsAddress());
News replaceNews=new News();
News oldNews =_adapter.getItem(currentIndex);
replaceNews.setTitle(oldNews.getTitle()+" ( "+String.valueOf(currentIndex)+" )");
replaceNews.setImageNews(Helpers.GetImageFromUrl(news.getImageNewsAddress()));
SharedVar.getCurrentNews().set(currentIndex, replaceNews);
}
_adapter.notifyDataSetChanged();
}
});
explanation : calling notifyDataSetChanged many times in a row, is a bad idea.
make your updates to the data, and then call it once!
your code was calling it twice for every news item.
Your are calling notifyDataSetChanged() in your for loop which is a bad practice and that to you are calling it twice. So remove notifyDataSetChanged() from your for loop. A better approach would be to move your code to an AsyncTask inside doInBackground() and then call notifyDataSetChanged() in your onPostexecute().
I need to get text from a website which is done in a new thread. Then i need to put that text in a list view.
The problem is that i cant set up array adapter for list view until text is put in the lists used in that adapter. Lists are filled in that thread used for connecting to website.
I tried to solve that by setting up adapter in new thread run by first thread. Program starts without errors, but nothing shows up in list view.
I am using List view code from this site http://www.vogella.com/articles/AndroidListView/article.html
Im a newbie in java and android so i hope you understand what im trying to do :)
Heres the code
package com.example.studentservis;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.R.string;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.Menu;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
public class MainActivity extends Activity {
String s;
List<String> headersList = new ArrayList<String>();
List<String> contentList = new ArrayList<String>();
ListView listview;
StableArrayAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listview = (ListView) findViewById(R.id.listView1);
threadStart();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
public void adapterInit()
{
adapter = new StableArrayAdapter(this, android.R.layout.simple_list_item_1, headersList);
listview.setAdapter(adapter);
}
private class StableArrayAdapter extends ArrayAdapter<String>{
HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();
public StableArrayAdapter(Context context, int textViewResourceId,
List<String> objects) {
super(context, textViewResourceId, objects);
// TODO Auto-generated constructor stub
for (int i = 0; i < objects.size(); ++i) {
mIdMap.put(objects.get(i), i);
}
}
#Override
public long getItemId(int position) {
String item = getItem(position);
return mIdMap.get(item);
}
#Override
public boolean hasStableIds() {
return true;
}
}
public void threadStart()
{
//txtView.setText(stringHandler.getString());
new Thread(new Runnable() { // thread
public void run(){
try
{
webRequest();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new Runnable()
{
#Override
public void run() {
// TODO Auto-generated method stub
adapterInit();
}
};
}
}).start();
}
public void webRequest() throws Exception{
String servisURL = "http://www.sczg.unizg.hr/student-servis/";
Document doc = Jsoup.connect(servisURL).get();
Elements jobNode = doc.select("div.jobBox");
Elements headersNode = jobNode.select("h1");
Elements contentNode = jobNode.select("content");
for(int i = 0; i < headersNode.size(); i++){
headersList.add(headersNode.get(i).text());
}
for(int i = 0; i < contentNode.size(); i++){
contentList.add(contentNode.get(i).text());
}
}
}
Hope this may work for you, here i used Asynchronous Task instead of thread
public class MainActivity extends Activity {
String s;
List<String> headersList = new ArrayList<String>();
List<String> contentList = new ArrayList<String>();
ListView listview;
StableArrayAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listview = (ListView) findViewById(R.id.listView1);
// threadStart();
// Here i implemented Asynchronous Task instead of Thread
new SampleAsyncTask().execute();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
public class SampleAsyncTask extends AsyncTask<Void, Void, Void> {
private final ProgressDialog dialog = new ProgressDialog(
MainActivity.this);
protected void onPreExecute() {
this.dialog.setMessage("Loading...");
this.dialog.setCancelable(false);
this.dialog.show();
}
#Override
protected Void doInBackground(Void... params) {
try {
webRequest();
adapter = new StableArrayAdapter(MainActivity.this,
android.R.layout.simple_list_item_1, headersList);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Void result) {
// Here if you wish to do future process for ex. move to another
// activity do here
listview.setAdapter(adapter);
if (dialog.isShowing()) {
dialog.dismiss();
}
}
}
private class StableArrayAdapter extends ArrayAdapter<String> {
HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();
public StableArrayAdapter(Context context, int textViewResourceId,
List<String> objects) {
super(context, textViewResourceId, objects);
// TODO Auto-generated constructor stub
for (int i = 0; i < objects.size(); ++i) {
mIdMap.put(objects.get(i), i);
}
}
#Override
public long getItemId(int position) {
String item = getItem(position);
return mIdMap.get(item);
}
#Override
public boolean hasStableIds() {
return true;
}
}
public void webRequest() throws Exception {
String servisURL = "http://www.sczg.unizg.hr/student-servis/";
Document doc = Jsoup.connect(servisURL).get();
Elements jobNode = doc.select("div.jobBox");
Elements headersNode = jobNode.select("h1");
Elements contentNode = jobNode.select("content");
for (int i = 0; i < headersNode.size(); i++) {
headersList.add(headersNode.get(i).text());
}
for (int i = 0; i < contentNode.size(); i++) {
contentList.add(contentNode.get(i).text());
}
}
}
At first I propose you to read this guide, especially about Using AsyncTask instead raw Thread.
At second, as I understand, you want to invoke adapterInit from UI thread?
So, you can try this:
runOnUiThread( // <-- method from Activity
new Runnable()
{
#Override
public void run() {
// TODO Auto-generated method stub
adapterInit();
}
}
);
Maybe the problem is that you are not calling the method notifyDataSetChanged() on the adapter to force it to update his informations, it's like notifying the adapter that the underlaying data were updated and that it needs to refresh the associated listview.
You should call it after you fetch the data from the website.
You can use Handler.
In the webRequest thread,When webRequest() finished,you use Handler to notice the main thread to adapterInit().Not use another thread in the webRequest thread.
A simple example.
#Override
public void onClick(DialogInterface dialog,
int which) {
setControlsEnable(false);
new Thread() {
public void run() {
WebserviceMethod wb = new WebserviceMethod();
if (wb.DeleteEmployee(
VerificationUtils
.GetInstance()
.CreateToken(),
personId) == 1) {
Message msg = new Message();
msg.obj = SwitchActivityValue.SWITCH_DELETEPERSON_OK;
mHandler.sendMessage(msg);
}
}.start();
}
#Override
public void handleMessage(Message msg){
super.handleMessage(msg);
SwitchActivityValue value = (SwitchActivityValue)msg.obj;
switch (value) {
case SWITCH_DELETEPERSON_OK:
ManageUtils.EmployeeListDataForAdmin.personInfos.clear();
ManageUtils.EmployeeListDataForAdmin.currentPage = 0;
mActivity.switchActivity(mValue);
break;
case SWITCH_DELETEPERSON_FAILED:
break;
default:
break;
}
mActivity.showMessage(value);
}
Such as the example,you can bind the data in the Handler.When the thread finished,it use hanlder to sendmessage to notice handleMessage handle others.
I've got a strange problem, a Dialog being created and called for "show()" but not being visible in my activity...
The thing is it goes through the call "show", I've seen it in the debugger, but nothing...
here is the code:
protected void initializeSpinners() {
spnPlayLists = (Spinner) findViewById(R.id.spnLists);
spnProviders = (Spinner) findViewById(R.id.spnProvider);
spnProviders.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> _spinner, View _parent,
int _pos, long _id) {
if (_spinner == spnProviders) {
String[] playListsId = core.getAllPlayListsFrom(_pos);
int items = playListsId.length;
**showProgressDialog(items);**
String[] playListsNames = new String[items];
String[] playListsThumbs = new String[items];
playLists = new PlayList[items];
for (int i = 0; i < items; i++) {
String id = playListsId[i];
PlayList playList = core.getPlayList(id, true);
playLists[i] = playList;
playListsNames[i] = playList.title;
playListsThumbs[i] = playList.thumb;
handle.sendEmptyMessage(i);
}
loadPlayLists(playListsNames, playListsThumbs);
myPd_bar.dismiss();
}
}
#Override
public void onNothingSelected(AdapterView<?> _arg0) {
}
});
ProvidersArrayAdapter providersAdapter = new ProvidersArrayAdapter(this);
spnProviders.setAdapter(providersAdapter);
}
and the function called up:
private void showProgressDialog(int _items) {
handle = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
myPd_bar.setProgress(msg.what + 1);
}
};
myPd_bar = new ProgressDialog(Intro.this);
myPd_bar.setMessage("Loading....");
myPd_bar.setTitle("Please Wait..");
myPd_bar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
myPd_bar.setProgress(0);
myPd_bar.setMax(_items);
**myPd_bar.show();**
}
what am I doing bad...?
It is possible that your dialog is getting dismissed before it appears. Basically your loop is not going long enough for the view to appear.
Have you tried to comment out the dismiss line and see if it appear then?
Finally I realized. I was holding the activity thread in the spinner so it won't show anything until it finishes!
here is my solution, using an asyntask (properly, I was using them badly on the playlist load, and blocking)
protected void setupDialog() {
handle = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what < 0){
loadPlayLists(playListsNames, playListsThumbs);
myPd_bar.dismiss();
} else {
myPd_bar.setProgress(msg.what + 1);
}
}
};
myPd_bar = new ProgressDialog(Intro.this);
myPd_bar.setMessage(WAIT_MESSAGE);
myPd_bar.setTitle(WAIT_TITLE);
myPd_bar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
myPd_bar.setProgress(0);
}
protected void initializeSpinners() {
spnPlayLists = (Spinner) findViewById(R.id.spnLists);
spnProviders = (Spinner) findViewById(R.id.spnProvider);
spnProviders.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> _spinner, View _parent,
int _pos, long _id) {
if (_spinner == spnProviders) {
String[] playListsId = core.getAllPlayListsFrom(_pos);
int items = playListsId.length;
myPd_bar.setMax(items);
myPd_bar.show();
new AsyncTask<String[], Integer, Long>(){
#Override
protected Long doInBackground(String[]... _playListsId) {
int items = _playListsId[0].length;
playListsNames = new String[items];
playListsThumbs = new String[items];
playLists = new PlayList[items];
for (int i = 0; i < items; i++) {
String id = _playListsId[0][i];
PlayList playList = core.getPlayList(id, true);
playLists[i] = playList;
playListsNames[i] = playList.title;
playListsThumbs[i] = playList.thumb;
publishProgress(i);
}
return null;
}
#Override
protected void onProgressUpdate(Integer... _progress) {
handle.sendEmptyMessage(_progress[0]);
}
#Override
protected void onPostExecute(Long _result) {
handle.sendEmptyMessage(-1);
}
}.execute(playListsId);
}
}
#Override
public void onNothingSelected(AdapterView<?> _arg0) {
}
});
ProvidersArrayAdapter providersAdapter = new ProvidersArrayAdapter(this);
spnProviders.setAdapter(providersAdapter);
}