I am unable to refresh my listview. I know there are lots of help available for this. But I am unable to get my listview refreshed.
Lemme edit my code a little bit showing the AsyncTask
There are two Activities. The first Activity is having the list view to see what is being shared and the second activity has an edit text box (to input inorder to share) and a button. On clicking the button, it returns me the string which is the json response and I need to add this in the previous activity.
Now the problem is, when I refresh the first page fully hitting the server it gets the response but this is not what I want. It should not go back to the server. It should simply add in the list view adapter.
I have commented the code in the PostExecute(). I have tried the everyway but it is not reflecting.
public class ShareAsyncTask extends AsyncTask<String, Void, ArrayList<EventsStreamBean>> {
public ProgressDialog pd = new ProgressDialog(EventStreamActivity.this);
String success_share_val;
#Override
protected ArrayList<EventsStreamBean> doInBackground(
String... result) {
// TODO Auto-generated method stub
JSONObject jsonobj = new JSONObject(result[0].toString());
success_share_val = jsonobj.getString(Constants.SUCCESS);
//checks the success value
if(success_share_val.equalsIgnoreCase("1")) {
JSONArray events_stream_share_array = jsonobj.getJSONArray("streamArray");
if(events_stream_share_array.length() > 0) {
for(int i=0; i<events_stream_share_array.length(); i++) {
EventsStreamBean events_stream_bean = new EventsStreamBean();
JSONObject events_stream_object = events_stream_share_array.getJSONObject(i);
events_stream_bean.setStreamId(events_stream_object.getString(Constants.STREAM_ID));
events_stream_bean.setStreamType(events_stream_object.getString(Constants.STREAM_TYPE));
events_stream_bean.setUserId(events_stream_object.getString(Constants.USER_ID));
events_stream_bean.setUserName(events_stream_object.getString(Constants.USER_NAME));
events_stream_bean.setUserType(events_stream_object.getString(Constants.USER_TYPE));
events_stream_bean.setUserAvatar(events_stream_object.getString(Constants.USER_AVATAR));
arraylist_events_stream.add(events_stream_bean);
}
}else {
Log.i("Test", "No Events Streams Available");
}
}
}catch(Exception e) {}
return arraylist_events_stream;
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
this.pd.setMessage("Loading....");
pd.setCanceledOnTouchOutside(false);
pd.setCancelable(false);
this.pd.show();
}
#Override
protected void onPostExecute(final ArrayList<EventsStreamBean> result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
if(this.pd.isShowing()) {
this.pd.dismiss();
}
Toast.makeText(EventStreamActivity.this, "Post shared successfully", Toast.LENGTH_SHORT).show();
new EventsStreamAsyncTask().execute(temp_val);
/*runOnUiThread(new Runnable() {
public void run() {
//EventStream_Customadapter adapter = (EventStream_Customadapter) list_view.getAdapter();
//adapter.clearData();
adapter.updateData(result);
//adapter = new EventStream_Customadapter(EventStreamActivity.this, arraylist_events_stream);
//list_view.setAdapter(adapter);
//adapter.notifyDataSetChanged();
}
});*/
}
}
You should call setAdapter() only once in your entire code.
Then add a method in your adapter that adds more data when you want to add more data or sets adapter item.
public void addMoreData(List<String> newItems) {
this.list.addAll(newItems);
}
public void setList(List<String> newList) {
this.list = newList;
}
Call notifyDataSetChanged() after you set new list or add more data.
as per what you want to achieve there is no need for you to use threads
have a look at the following link it shows how to do it in the same activity
http://wptrafficanalyzer.in/blog/dynamically-add-items-to-listview-in-android/
In this they have done it in a single activity. if you want to do it with 2 activities let me know i will tell you how to do it.
Related
I know this Question asked so many times but i cant find mistake
I was checked all things what is am doing wrong but I cant find what I did mistake.
I am using back4App for back end.
I am just retrieve data from that and just want to show in my listview.
I was set log to check data which i am retrieving so it show arraylist size perfect in doInbackground method. but when I return it to postexecute and there i am also check size of it.but it show 0 there.
dont know what mistake i was did.
My code is below:
public class HomeActivity extends AppCompatActivity {
ProgressDialog mProgressDialog;
ArrayList<String> items;
ListView listView;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
listView = (ListView) findViewById(R.id.listview);
items=new ArrayList<>();
new GetServices().execute();
}
private class GetServices extends AsyncTask<Void, Void, ArrayList<String>> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Create a progressdialog
mProgressDialog = new ProgressDialog(HomeActivity.this);
// Set progressdialog title
mProgressDialog.setTitle("Parse.com Simple ListView Tutorial");
// Set progressdialog message
mProgressDialog.setMessage("Loading...");
mProgressDialog.setIndeterminate(false);
// Show progressdialog
mProgressDialog.show();
}
#Override
protected ArrayList<String> doInBackground(Void... params) {
// Locate the class table named "services" in Parse.com
ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("services");
query.orderByAscending("updatedAt");
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
items.clear();
Log.i("TAG", "datasize=>" + objects.size());
List<String> temp = new ArrayList<String>();
for (ParseObject services : objects) {
temp.clear();
items.add(services.getString("serviceTitle"));
temp = services.getList("serviceDetails");
items.add(Util.getHtmlText(temp));
}
Log.i("TAG", "itemsize=>" + items.size());
} else {
e.printStackTrace();
}
}
});
return items;
}
#Override
protected void onPostExecute(ArrayList<String> strings) {
super.onPostExecute(strings);
Log.i("TAG", "resultsize=>" + strings.size());
for (int i = 0; i < strings.size(); i++) {
Log.i("TAG", "==>" + strings.get(i));
}
// Pass the results into an ArrayAdapter
CustomServiceListAdapter adapter = new CustomServiceListAdapter(HomeActivity.this, R.layout.custom_fragment_service_list_item, strings);
// Binds the Adapter to the ListView
listView.setAdapter(adapter);
// Close the progressdialog
mProgressDialog.dismiss();
// Capture button clicks on ListView items
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// Send single item click data to SingleItemView Class
Intent i = new Intent(HomeActivity.this,
DetailsActivity.class);
// Pass data "name" followed by the position
i.putExtra("data", items.get(position));
// Open SingleItemView.java Activity
startActivity(i);
}
});
}
}}
My Logcat show below:
05-20 13:10:28.661 19099-19099/com.example.apexweb I/TAG: resultsize=>0
05-20 13:10:29.409 19099-19099/com.example.apexweb I/TAG: datasize=>4
05-20 13:10:29.410 19099-19099/com.example.apexweb I/TAG: itemsize=>8
Accordingly to the documentation findInBackground retrieves a list of ParseObjects that satisfy this query from the source in a background thread, and gets you the results in the callback. doInBackground does not wait until the callback with the results is called. That's why in onPostExecute the size is still 0. Since doInBackground runs already on a different thread, a second level of asynchronously is not necessary. You can call directly find(). Alternatively you can get rid of the AsyncTask and run findInBackground with the callback from the UI Thread
I want to develop an Android application which asks a server for some data, and displays these data in a ListView.
Currently, I am using a single Activity (without fragments), and the layout is very simple: it consists of an ImageView, an EditText and a ListView. When the ImageView is clicked it gets the content of the EditText and sends it to the server as a new item and automatically updates the Listview (am calling the method of retreiving the objects after the add operation).
I created an AsyncTask class with a progress dialog inside the Activity which the job in background is getting the objects from the server and then assigning them to a List (member of the enclosing class).
With that practice, am facing a lot of problems: the list gets displayed correctly but very slowly! and when I press the ImageView the AsyncTask is then called to do its job after adding the new item but the problem is that its dialog never dismisses.
My question is what is the best practice with this situation in Android? what is the best design pattern? should I use fragments? How should I manage my Threads?
UDATE:
here is the AsyncTask:
class RemoteDataTask extends AsyncTask<Void, Void, Void> {
private UserDetailsActivity context;
RemoteDataTask(UserDetailsActivity context) {
this.context = context;
}
#Override
protected void onPreExecute() {
super.onPreExecute();;
mProgressDialog = ProgressDialog.show(context, "Looking for posts", "Loading...", true, false);
}
#Override
protected Void doInBackground(Void... params) {
UserDetailsActivity.this.posts.clear();
posts = new PostManager(context).userPosts(ParseUser.getCurrentUser());
return null;
}
#Override
protected void onPostExecute(Void result) {
postList = (ListView) findViewById(R.id.post_list);
adapter = new PostsListAdapter(context, UserDetailsActivity.this.posts);
postList.setAdapter(adapter);
mProgressDialog.dismiss();
}
}
And the method wich retreives the posts:
public void refreshPostList() {
try {
BusInfo.getInstance().register(UserDetailsActivity.this); // register the Bus to recieve results.
} catch (Exception e) {
Log.d("My application says : ;) ", "Erro registering " + e);
}
pd = ProgressDialog.show(this, "Please Wait", "Loading");
new ExprienceEdit(this, "hello").execute();
}
And the Button with its method
public void newPost(View v) {
ParseObject post = new ParseObject("Post");
post.put("content", editText.getText().toString());
post.saveInBackground();
refreshPostList();
}
<ImageView
android:id="#+id/new_post"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:onClick="newPost"
android:padding="10dp"
android:src="#drawable/ic_action_post" />
Regarding the progress dialog not being dismissed:
Where is mProgressDialog dialog declared? I suggest you move it into the RemoteDataTask. (I'm guessing you are at some point overriding the current instance and therefore the dismiss isn't working)
Regarding the slow refresh of the list, post your Adapter code. You should do correct recycling of views and you shouldn't recreate the Adapter everytime but set the data and call notifyDataSetChanged so the listView will recycle the views with the new data. Look into this answer regarding correct recycling of views: https://stackoverflow.com/a/6923513/348378
Edit 1
I also suggest this to prevent having multiple refreshTasks:
public void refreshPostList() {
if(dataTask == null) {
dataTask = new RemoteDataTask(this).execute();
}
}
#Override
protected void onPostExecute(Void result) {
// you stuff
dataTask = null;
}
You can also consider cancelling the current task and starting a new one depending on required behavior.
you should pass ProgressDialog to your AsyncTask class constructor and in any class that want to use AsyncTask class(in your case RemoteDataTask) you should instantiate progress dialog and pass as second argument to your RemoteDataTask to control the visibility from specific custom class.
maybe this help.
The best way to deal with asynctasks is by using otto :
Otto actually is a singltone bus : please refer to this website http://square.github.io/otto/
Any piece of code would be great to help you more with the problem you are facing.
Any questions I am ready to answer.
BusInfo.getInstance.register(ActivityName.this) // register the Bus to recieve results.
pd = ProgressDialog.show(ActivityName.this, "Please Wait", "Loading");
new ExperienceEdit(getApplicationContext(), "hello").execute(); //async task to be executed let us say on button click
Now the experience edit is:
public class ExperienceEdit extends AsyncTask<Void, Void, String> {
Context c;
String id;
public ExperienceEdit(Context c, String id\) {
this.c = c;
this.id = id;
}
#Override
protected String doInBackground(Void... voids) {
//right the call to back here
}
#Override
public void onPostExecute(String result) {
try {
BusInfo.getInstance().post(new ExperienceEditResult(result));
} catch (Exception e) {
e.printStackTrace();
}
}
}
The result after posting is subscribed at the activity like this :
#Subscribe
public void onAsyncTaskResult(EditExperienceResult result) {
if (pd != null)
pd.dismiss();
object = result.getResult();
if (object != null) {
if (object.equals("success")) {
Toast.makeText(getApplicationContext(), "Success", Toast.LENGTH_SHORT).show();
onBackPressed();
} else Toast.makeText(getApplicationContext(), "Failure", Toast.LENGTH_SHORT).show();
} else
Toast.makeText(getApplicationContext(), "Please try again later", Toast.LENGTH_SHORT).show();
}
The ExperienceEditResult here happens to be a string (you can have it whatever you want) :
public class ExperienceEditResult {
private String result;
public ExperienceEditResult(String result) {
this.result = result;
}
public String getResult() {
return result;
}
}
The BusInfo class is :
public class BusInfo {
private static final Bus BUS = new Bus();
public static Bus getInstance() {
return BUS;
}
}
Do not forget to unregister the bus onDestroy of the activity: BusInfo.getInstance().unregister(ActivityName.this);
If you aslso want to prevent the progress dialogue from always showing because sometimes it is showing twice due to a double click on button add this : if(pd!=null&&pd.isShowing()){
Log.v("pd is showing","showing");
} else {pd= ProgressDialgue.show...}
I have an Activity that extends a ListActivity , in onCreate method i set the contentView and call an AsyncTask to load data and the list get filled as I want, the problem is when I check for example the detail activity and want go back the the listView: I get the onCreate method executed, data are loaded again and the listView is scrolled to the top loosing my previous position.
What I want to achieve is something like google gmail app for example: the list view get loaded once and the scroll position is saved.
I've looked so much over here and I tried many solutions but none is working.
What is the best way to achieve this scenario?
my activity :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
new LoadEvents().execute();
}
my asyncTask :
class LoadEvents extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(Home.this);
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
protected String doInBackground(String... args) {
List<NameValuePair> params = new ArrayList<NameValuePair>();
JSONObject json = jParser.makeHttpRequest(AgendaIConstantes.URL_EVENTS, "GET", params);
......Processing
eventList.add(map);
}
} else {
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String file_url) {
pDialog.dismiss();
runOnUiThread(new Runnable() {
public void run() {
ListAdapter adapterRes = getListAdapter();
if(adapterRes == null){
ListAdapter adapter = new SimpleAdapter(Home.this, eventList,R.layout.list_item,
new String[] { .....},
new int[] { .....});
setListAdapter(adapter);
}
}
});
}
Just do not execute your loading task every call of onCreate method. You can use either boolean flag in your activity or save state using onSaveInstanceState.
By the way, calling getListAdapter in onPostExecute is not very ok method and your null checking shows it.
I have a requirement where i need to parse the content of a URL in JSON format. I am able to do that successfully. But i need to save the contents of the URL in a array list and pass them back to the calling functions. Below is the code snippet of what i am trying to achieve.
#Override
protected ArrayList<String> onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
dialog.dismiss();
return ar; // ar is the arraylist i have created and updated it with the content of the url.
}
But running this gives an error. Can anyone please suggest how i can make this possible. However, when i make the return type of onPostExecute as void and toast the contents, its displaying properly. When i call this after the execute, its returning null even though i have updated the contents in doinbackground(). Hence i am unable to get the return values on arraylist format.
// Calling function
Myadapter.execute();
ArrayList<string> str = new ArrayList<string>();
str = print();
// Here str is getting null
// Called function
public ArrayList<String> print() {
ArrayList<String> names = new ArrayList<String>();
for(int i=0;i<al.size();i++)
{
names.add(al.get(i).getConstituencyName());
}
return names;
}
Use a handler
In your activity
mHandler = new Handler() {
#Override public void handleMessage(Message msg) {
ArrayList s=(ArrayList)msg.obj;
tv.setText("Result = "+s.get(0));
}
};
In your onPostexecute
Message msg=new Message();
msg.obj=ar;
mHandler.sendMessage(msg);
The proper way would be to let your activity implement an interface, and when you instantiate the AsyncTask pass the current activity as a parameter to the constructor. Then in onPostExecute() invoke the callback method defined in the Activity and pass the json result as an argument.
Something like this:
interface OnTaskFinished {
void onTaskFinished(String result);
}
public class MainActivity extends Activity implements OnTaskFinished {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ....
new MyAsyncTask(this).execute();
}
#Override
public void onTaskFinished(String result) {
// Process the json result here how you need.
}
}
And this is how the scheleton of your AsyncTask should look like:
private class MyAsyncTask extends AsyncTask<Void, Void, String> {
private final OnTaskFinished listener;
public MyAsyncTask(OnTaskFinished listener) {
this.listener = listener;
}
// ...
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
listener.onTaskFinished(result);
}
}
I'm still working on my application that has to store RSS data localy.
So far i managed to create a local database and parse the online RSS feed.
I also managed to put this information in the database so now the app will also be available while being offline.
However i can't seem to figure out how to do the following:
I have 2 buttons, one of them reads the database titles and will go to a detailed page of your selection (still working on that)
My current problem is that i can't seem to add a loading bar to pop up on the screen while the application is downloading the data from the internet. The screen is just blank for like 10 seconds and then the list pops up. here is the code that i'm using:
public class SynchDB_Activity extends ListActivity {
public List<Message> messages;
public List<String> titles;
//ProgressDialog dialog = ProgressDialog.show(SynchDB_Activity.this, "", "Downloading data...", true);
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.animal_list_view);
loadFeed();
}
private void loadFeed(){
try{
BaseFeedParser parser = new BaseFeedParser();
messages = parser.parse();
List<String> titles = new ArrayList<String>(messages.size());
DBAdapter db = new DBAdapter(this);
for (Message msg : messages){
titles.add(msg.getTitle());
db.addRow(
msg.getTitle(),
msg.getDescription(),
"bla",
"http:/",
msg.getLink());
}
//dialog.dismiss();
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.row,titles);
this.setListAdapter(adapter);
} catch (Throwable t){
Log.e("AndroidNews",t.getMessage(),t);
}
}
So this code works and puts all the data in the local database. However i just cant make that loading bar working and it's driving me crazy.
If anyone could help me out i would be gratefull!!!
I've been googling all day and nothing seems to do the trick....
many thanks
edit: As you can see in the code i display the list when its done. This is not nececary, but from the moment i remove the ArrayAdapter the app won't work anymore.
Keep in mind that this all is quite new for me and i think that the main part where things are going wrong is useing the different layouts...
Use Async task and progress bar as shown here:
public void getrss()
{
try{
class test extends AsyncTask{
TextView tv_per;
int mprogress;
Dialog UpdateDialog = new Dialog(ClassContext);
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
mprogress = 0;
UpdateDialog.setTitle(getResources().getString(R.string.app_name));
UpdateDialog.setContentView(R.layout.horizontalprogressdialog);
TextView dialog_message = (TextView)UpdateDialog.findViewById(R.id.titleTvLeft);
tv_per = (TextView)UpdateDialog.findViewById(R.id.hpd_tv_percentage);
dialog_message.setText(getResources().getString(R.string.dialog_retrieving_data));
dialog_message.setGravity(Gravity.RIGHT);
UpdateDialog.setCancelable(false);
UpdateDialog.show();
super.onPreExecute();
}
#Override
protected void onProgressUpdate(Object... values) {
// TODO Auto-generated method stub
ProgressBar update = (ProgressBar)UpdateDialog.findViewById(R.id.horizontalProgressBar);
update.setProgress((Integer) values[0]);
int percent = (Integer) values[0];
if(percent>=100)
{
percent=100;
}
tv_per = (TextView)UpdateDialog.findViewById(R.id.hpd_tv_percentage);
tv_per.setText(""+percent);
}
#Override
protected Object doInBackground(Object... params) {
// TODO Auto-generated method stub
//your code
}
super.onPostExecute(result);
UpdateDialog.dismiss();
}
}
new test().execute(null);
}
catch(Exception e)
{
e.printStackTrace();
}
}
You probably want to use AsyncTask.