I have an AsyncTask which loads Tweets from Twitter.
I also have a PullToRefresh ListView... Whenever i pull to refresh it, the listview immediately clears and as soon as the data has been loaded, it's getting filled into the listview.
I have other ListViews in my App all with the same stuff (PullToRefresh and Async data loading...). On the other ListViews this does not happen. Only on the Twitter ListView. What am I doing wrong?
Here is my Code:
public class TwitterDownloader extends AsyncTask<Void, Void, String> {
final Handler mHandler = new Handler();
public TwitterDownloader() {
}
#Override
public void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(Void... params) {
twitter4j.Twitter twitter = new TwitterFactory().getInstance();
listTweets.clear();
List<twitter4j.Status> statuses = null;
try {
statuses = twitter.getUserTimeline(
MainActivity.TWITTER_USERNAME, new Paging(1, 50));
} catch (TwitterException e) {
e.printStackTrace();
Log.e(MainActivity.LOG_TAG, "TwitterException");
}
try {
for (twitter4j.Status status : statuses) {
listTweets.add(status.getText());
}
} catch (NullPointerException npe) {
}
return null;
}
#Override
public void onPostExecute(String unused) {
MyCustomAdapter myAdapter = new MyCustomAdapter(myContext,
R.layout.row_twitter, listTweets);
setListAdapter(myAdapter);
getListView().setTextFilterEnabled(true);
String lastUpdate = (new SimpleDateFormat(
"HH:mm")).format(new Date());
pullToRefreshView.onRefreshComplete();
pullToRefreshView.setLastUpdatedLabel(getString(R.string.last_updated) + ": "
+ lastUpdate);
}
I am not sure about this but in doInBackground method of AsyncTask, you are doing listTweets.clear();. After getting result, you are adding data to it. May be this is causing problems.
I finally fixed it by adding all my clear() statements right before I fill up my list again (which is inside a try catch).
So the new code inside my doInBackground method is:
try {
listTweets.clear();
listUsernames.clear();
listDates.clear();
listImageURLs.clear();
listURLsOfTweets.clear();
for (twitter4j.Status status : statuses) {
listTweets.add(status.getText());
listUsernames.add(status.getUser().getName());
listDates.add(android.text.format.DateFormat
.getDateFormat(getApplicationContext()).format(
status.getCreatedAt())
+ " "
+ android.text.format.DateFormat.getTimeFormat(
getApplicationContext()).format(
status.getCreatedAt()));
listImageURLs.add(status.getUser().getProfileImageURL()
.toString());
StringBuffer address = new StringBuffer();
address.append("http://twitter.com/#!/");
address.append(status.getUser().getScreenName());
address.append("/status/");
address.append(status.getId());
listURLsOfTweets.add(address.toString());
}
Related
when i run my code, it returns a value as "null"`
private class MessageActivityLoaderTask extends AsyncTask<Void, Void, Contentlist> {
private LinkedMultiValueMap<String, String> formData;
Activity activity;
public MessageActivityLoaderTask(Activity activity) {
this.activity = activity;
}
#Override
protected void onPreExecute() {
formData = new LinkedMultiValueMap<String, String>();
mProgress.setMessage("Please wait..");
mProgress.show();
}
#Override
protected Contentlist doInBackground(Void... params) {
String url = getString(R.string.base_url) + "/example/example1/1";
Contentlist mess = null;
try {
mess = RestUtils.exchangeFormData(url, HttpMethod.GET, formData, Contentlist.class);
} catch (Exception e) {
e.printStackTrace();
mProgress.dismiss();
}
return mess;
}
protected void onPostExecute(Contentlist result) {
if (result== null) {
Toast message = Toast.makeText(ListobjectsActivity.this, "result is empty", Toast.LENGTH_SHORT);
message.show();
} else {
ListactivityAdapter adapter = new ListactivityAdapter(this.activity, result.getContents());
ListView list = (ListView) activity.findViewById(R.id.account);
list.setAdapter(adapter);
mProgress.dismiss();
}
}`
Your AsyncTask looks like it is set up correctly, so onPostExecute() will receive the ContentList returned by doInBackgroun(). Since onPostExecute() is seeing a null, then doInBackground() is returning a null. That means that either doInBackground() is getting an exception and mess is never set to a non-null value by falling through the catch or RestUtils.exchangeFormData() is returning a null.
I suggest that you debug the code in this area to see what is really going on. It is not likely to be an AsyncTask problem.
I want display progress bar in activity while loading data and when loading complete, progress bar to be hide (GONE)!
and try this code : (button click to load data)
private void allMoment() {
BTN_ALL.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
TBL_MOMENT = new TableMoment(DB_HELPER);
// MOMENTS = TBL_MOMENT.MOMENT_LIST();
new loadTask().execute();
filterResult();
EDT_SEARCH.setText("");
} catch (Exception e) {
displaySnackBar(v, "خطا:" + "\n" + e.toString());
}
}
});
}
and Task method :
private class loadTask extends AsyncTask<String, Integer, Boolean> {
#Override
protected void onPreExecute() {
PROGRESS_LOADER.setVisibility(View.VISIBLE);
super.onPreExecute();
}
#Override
protected void onPostExecute(Boolean result) {
PROGRESS_LOADER.setVisibility(View.GONE);
adapter.notifyDataSetChanged();
super.onPostExecute(result);
}
#Override
protected Boolean doInBackground(String... params) {
MOMENTS = TBL_MOMENT.MOMENT_LIST();
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
and fill recycler with dapter :
private void filterResult() {
try {
adapter = new HistoryAdapter(this, MOMENTS);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
} catch (Exception e) {
displayToast(this, "خطای آداپتر:" + "\n" + e.toString());
}
}
but data become load and fill into recyclerview and don't show progress bar
how to fix this problem ?
You have :
new loadTask().execute();
filterResult();
EDT_SEARCH.setText("");
This execute() call returns inmediatly, if you execute an AsyncTask waiting for a result you don't have a result until AsyncTask.doInBackground() returns and AsyncTask.onPostExecuted() is called
Is this filterResult(); time consuming ? ... if the main UI thread is blocked then the UI will be not updated.
How do you want this progress bar to work? You can search for a gif on the Internet, once you find one that suits your criteria you have to display it when you open the activity. When you populate your recyclerView you set the visibility of the gif as GONE.
I have an AsyncTask that loads all my data on parse.com, then the user has a checkbox to select the categories he wants to display.
Once I get those choices (from a separate class via an interface), I reload the asyncTask, but It still lists everything (like if the array of choices gets erased/reloaded).
here is my code to get the selected categories :
#Override
public void onOkay(ArrayList<Integer> selected) {
StringBuilder stringBuilder = new StringBuilder();
if (selected.size() != 0) {
for (int i = 0; i < selected.size(); i++) {
String categories = selectedArray[selected.get(i)];
stringBuilder = stringBuilder.append(", " + categories);
}
//this is to display the content of the selectedArray :
Toast.makeText(this, "You have selected: "
+ stringBuilder.toString(), Toast.LENGTH_SHORT).show();
//reloading the AsyncTask class :
new RemoteDataTask().execute();
}
}
My AsyncTask :
private class RemoteDataTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
//timer and progressdialog...
}
#Override
protected Void doInBackground(Void... params) {
list_of_articles = new ArrayList<Articles>();
try {
// Locate the class table named "Article" in Parse.com
ParseQuery<ParseObject> query = new ParseQuery<ParseObject>(
"Article");
query.whereWithinKilometers("Localisation_Vendeur", device_location, rayon);
//this is the query I use :
query.whereContainedIn ("Category",Arrays.asList(selectedArray));
ob = query.find();
for (ParseObject article : ob) {
// Locate images in article_image column
ParseFile image = (ParseFile) article.get("label1");
Articles map = new Articles();
map.setArticle_label1((String) article.get("label2"));
map.setArticle_label2((String) article.get("label3"));
map.setArticle_category((String) article.get("Category"));
map.setArticle_label4((String) article.get("label4"));
map.setArticle_image(image.getUrl());
list_of_articles.add(map);
}
} catch (ParseException e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
listview = (ListView) findViewById(R.id.listview);
// Pass the results into ListViewAdapter.java
adapter = new ListViewAdapter(MainActivity.this,
list_of_articles);
// Binds the Adapter to the ListView
listview.setAdapter(adapter);
// Close the progressdialog
mProgressDialog.dismiss();
}
}
How can I make that work ? Keep in mind that the query works, i've tested with an array that i filled manually and it works.
Thanks.
You should pass categories that user wants to display as arguments to AsyncTask through AsyncTask.execute(Params... params). They will be available in AsyncTask.doInBackground method as that method parameters. Use them inside doInBackgorund method to set your query appropriately.
private class RemoteDataTask extends AsyncTask<List<String>, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
//timer and progressdialog...
}
#Override
protected Void doInBackground(List<String>... params) {
list_of_articles = new ArrayList<Articles>();
try {
// Locate the class table named "Article" in Parse.com
ParseQuery<ParseObject> query = new ParseQuery<ParseObject>(
"Article");
query.whereWithinKilometers("Localisation_Vendeur", device_location, rayon);
//this is the query I use :
query.whereContainedIn ("Category", params[0]);
ob = query.find();
for (ParseObject article : ob) {
// Locate images in article_image column
ParseFile image = (ParseFile) article.get("label1");
Articles map = new Articles();
map.setArticle_label1((String) article.get("label2"));
map.setArticle_label2((String) article.get("label3"));
map.setArticle_category((String) article.get("Category"));
map.setArticle_label4((String) article.get("label4"));
map.setArticle_image(image.getUrl());
list_of_articles.add(map);
}
} catch (ParseException e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
listview = (ListView) findViewById(R.id.listview);
// Pass the results into ListViewAdapter.java
adapter = new ListViewAdapter(MainActivity.this,
list_of_articles);
// Binds the Adapter to the ListView
listview.setAdapter(adapter);
// Close the progressdialog
mProgressDialog.dismiss();
}
}
Then in code run AsyncTask by calling new RemoteDataTask().execute(Arrays.asList(selectedArray)). Make sure that selectedArray is updated properly before every call of AsyncTask.
I have a list called statusses and among it the text needed which are the tweets called status. I want to set the status to listview.
public class MainActivity extends Activity {
ListView i;
List<Status> statusess;
ConfigurationBuilder cb;
twitter4j.Status status3;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
i = (ListView) findViewById(R.id.listView1);
new LongOperation().execute("");
}
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
TwitterFactory tf = new TwitterFactory(cb.build());
Twitter twitter = tf.getInstance();
String[] srch = new String[] {"Obama"};
ResponseList<User> users = null;
try {
users = twitter.lookupUsers(srch);
} catch (TwitterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (User user : users) {
System.out.println("Friend's Name " + user.getName()); // this print my friends name
if (user.getStatus() != null)
{
System.out.println("Friend timeline");
try {
statusess = twitter.getUserTimeline(user.getName());
} catch (TwitterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (twitter4j.Status status3 : statusess)
{
System.out.println(status3.getText());
}
}
}
return null;
}
#Override
protected void onPostExecute(String result) {
}
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(Void... values) {
}
}
now this System.out.println(status3.getText()); works 100%, the tweets are showing in the console. but how do I get them to the listview in onPostExecute?
I tried
i.setAdapter(new ArrayAdapter<twitter4j.Status>(MainActivity.this,
android.R.layout.simple_list_item_1, statusess));
But I get a lot of text not needed, I need only status3 which is text(tweet), this displays a lot of stuff like tweet id, retweet, followers, etc ..
I also tried this
#Override
protected void onPostExecute(String result) {
for (twitter4j.Status status3 : statusess)
{
i.setAdapter(new ArrayAdapter<statusess>(MainActivity.this,
android.R.layout.simple_list_item_1, status3.getText()));
}
}
but didn't work, a lot of red line xD
users = twitter.lookupUsers(srch);
This gives you a list of users. You are running a for-loop to iterate through the list, changing statuses on each iteration. When the for-loop ends, statuses holds the status list(returned by twitter.getUserTimeline(user.getName())) of the last user. Is this really what you want?
For example, you can display the user list that is returned using twitter.lookupUsers(srch), in the ListView. And, on a item click event, display the status list for that user.
Once you decide on the user for whom you need the status list, do the following:
// Declare an ArrayList with class scope
ArrayList<String> statusListTextOnly;
// Initialize it in doInBackground()
#Override
protected String doInBackground(String... params) {
....
....
statusListTextOnly = new ArrayList<String>();
// Initialize 'statuses' for the user that you have decided on
statusess = twitter.getUserTimeline(user.getName());
// Run a for-loop to fill 'statusListTextOnly'
// We will use 'statusListTextOnly' with the ArrayAdapter
for (twitter4j.Status status3 : statusess) {
statusListTextOnly.add(status3.getText());
}
}
// Initialize/reset ArrayAdapter
#Override
protected void onPostExecute(String result) {
i.setAdapter(new ArrayAdapter<String>(MainActivity.this,
android.R.layout.simple_list_item_1, statusListTextOnly));
}
The problem with your code lies here:
i.setAdapter(new ArrayAdapter<twitter4j.Status>(MainActivity.this,
android.R.layout.simple_list_item_1, statusess));
Objects passed to an ArrayAdapter are displayed using the toString() method. Now, toString() is mostly overriden for custom objects and serves the purpose of providing a meaningful description of the object itself. It can be overriden to provide literally any kind of information in a String format. In case of Status objects, toString() returns a bit more than what you need. So, we extract the relevant info using Status#getText() and store it in a separate ArrayList.
Your second attempt has problems as well:
#Override
protected void onPostExecute(String result) {
for (twitter4j.Status status3 : statusess) {
i.setAdapter(new ArrayAdapter<statusess>(MainActivity.this,
android.R.layout.simple_list_item_1, status3.getText()));
}
}
Here, you are setting the generic parameter of ArrayAdapter to a variable('statuses'): the generic parameter should be a class. Next, you pass a String as the last argument, whereas an ArrayAdapter's constructor can either take an array of objects, or an ArrayList. Third, you are creating a new instance of your ArrayAdapter and setting it to the ListView on each iteration of the for-loop. This is logically incorrect. You need one instance of an ArrayAdapter and you only need to set it once.
What else can you do:
Create a custom ArrayAdapter that affords new functionality, for example: showing of images along with text.
Dig into BaseAdapter: Highly customizable, all-purpose adapter.
package com.example.twitterdemo;
import java.util.List;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
public final class GetTimeLines {
*//**
* Usage: java twitter4j.examples.GetTimelines ID Password
* #param args String[]
*//*
public static void main(String[] args) {
Twitter unauthenticatedTwitter = new TwitterFactory()
.getInstance();
System.out.println("Showing public timeline.");
try {
List<Status> statuses = unauthenticatedTwitter
.getUserTimeline();
for (Status status : statuses) {
System.out.println(status.getUser().getName() + ":"
+ status.getText());
}
if (args.length < 2) {
System.out
.println("You need to specify TwitterID/Password combination to show UserTimelines.");
System.out
.println("Usage: java twitter4j.examples.GetTimelines ID Password");
System.exit(0);
}
// Other methods require authentication
Twitter twitter = new TwitterFactory().getInstance();
statuses = twitter.getUserTimeline();
System.out.println("------------------------------");
System.out.println("Showing " + args[0]
+ "'s friends timeline.");
for (Status status : statuses) {
System.out.println(status.getUser().getName() + ":"
+ status.getText());
}
statuses = twitter.getUserTimeline();
System.out.println("------------------------------");
System.out.println("Showing " + args[0] + "'s timeline.");
for (Status status : statuses) {
System.out.println(status.getUser().getName() + ":"
+ status.getText());
}
Status status = twitter.showStatus(81642112l);
System.out.println("------------------------------");
System.out.println("Showing " + status.getUser().getName()
+ "'s status updated at " + status.getCreatedAt());
System.out.println(status.getText());
System.exit(0);
} catch (TwitterException te) {
System.out.println("Failed to get timeline: "
+ te.getMessage());
System.exit(-1);
}
}
}
I am trying to use ProgressDialog. when i run my app the Progress Dialog box show and disappear after 1 second. I want to show it on completion of my process.. Here is my code:
public class MainActivity extends Activity {
android.view.View.OnClickListener mSearchListenerListener;
private ProgressDialog dialog;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new YourCustomAsyncTask().execute(new String[] {null, null});
}
private class YourCustomAsyncTask extends AsyncTask <String, Void, Void> {
protected void onPreExecute() {
dialog = new ProgressDialog(MainActivity.this);
dialog.setMessage("Loading....");
dialog.setIndeterminate(true);
dialog.setCancelable(true);
dialog.show(); //Maybe you should call it in ruinOnUIThread in doInBackGround as suggested from a previous answer
}
protected void doInBackground(String strings) {
try {
// search(strings[0], string[1]);
runOnUiThread(new Runnable() {
public void run() {
// updateMapWithResult(); //Or call it onPostExecute before progressDialog's dismiss. I believe this method updates the UI so it should run on UI thread
}
});
} catch(Exception e) {
}
}
#Override
protected void onPostExecute(Void params) {
dialog.dismiss();
//result
}
#Override
protected Void doInBackground(String... params) {
// TODO Auto-generated method stub
return null;
}
}
}
Updated Question:
#Override
public void onCreate(SQLiteDatabase db) {
mDatabase = db;
Log.i("PATH",""+mDatabase.getPath());
mDatabase.execSQL(FTS_TABLE_CREATE);
loadDictionary();
}
/**
* Starts a thread to load the database table with words
*/
private void loadDictionary() {
new Thread(new Runnable() {
public void run() {
try {
loadWords();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}).start();
}
private void loadWords() throws IOException {
Log.d(TAG, "Loading words...");
for(int i=0;i<=25;i++)
{ //***//
final Resources resources = mHelperContext.getResources();
InputStream inputStream = resources.openRawResource(raw_textFiles[i]);
//InputStream inputStream = resources.openRawResource(R.raw.definitions);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
try {
StringBuilder sb = new StringBuilder();
while ((word = reader.readLine()) != null)
{
sb.append(word);
// Log.i("WORD in Parser", ""+word);
}
String contents = sb.toString();
StringTokenizer st = new StringTokenizer(contents, "||");
while (st.hasMoreElements()) {
String row = st.nextElement().toString();
String title = row.substring(0, row.indexOf("$$$"));
String desc = row.substring(row.indexOf("$$$") + 3);
// Log.i("Strings in Database",""+title+""+desc);
long id = addWord(title,desc);
if (id < 0) {
Log.e(TAG, "unable to add word: " + title);
}
}
} finally {
reader.close();
}
}
Log.d(TAG, "DONE loading words.");
}
I want to show ProgressDialogue box untill all words are not entered in the database. This code is in inner calss which extends SQLITEHELPER. so how to can i use ProgressDialogue in that inner class and run my addWords() method in background.
You cannot have this
runOnUiThread(new Runnable() {
public void run() {
// updateMapWithResult(); //Or call it onPostExecute before progressDialog's dismiss. I believe this method updates the UI so it should run on UI thread
}
});
in your doInBackground().
Progress dialog doesn't take priority when there is some other action being performed on the main UI thread. They are intended only when the actions are done in the background. runonUIthread inside doInBackground will not help you. And this is normal behavior for the progressdialog to be visible only for few seconds.
You have two doInBackground() methods inside your AsyncTask Class. Remove the runOnUiThread() from First doInBackground() and move it to second doInBackground() which has #Override annotation.
I don't know whether you wantedly written two doInBackground() methods or by mistake but it is not good to have such confusion between the Method. Your AsyncTask is not calling the first doInBackground() and it will call doInBackground() which has #Override annotation. So your ProgressDialog is dismissed in 1 second of time as it returns null immediately.