On my android app, I use the Parse.com online database to store my data. In the onCreate() method of my activity, I use the method findInBackground() to asynchronously load data.
The findInBackground() method does not initially reconnect to the activity and continue to run forever. However, if I click on the home button of my phone and then re-load the app, the findInBackGround() method finally reconnects and load the data.
I would like to:
make the findInBackground() method reconnect with the activity without needing to reload the app
show a loading image (animated gif ?) while data is loading.
Would you guys have any advice on my problem ?
Thank you in advance for your help,
Alex
PS: I already tried the find() method of parse. Even if it reconnects automatically with the app, I don't think it's the right way to proceed since it blocks the UI of the caller activity until data is loaded.
==================================================================================
I finally found the answers to my questions:
I put the code to populate the listView INSIDE a method of the findCallBack class. Thus, I make sure I will use the result of the findInBackground() method only AFTER it has finished run. Previously, I had put the code to populate the listView OUTSIDE of the findCallBack class, so even if it came after in my code, it was actually executed before the end of findInBackground(), so didn't work.
For the loading image, I used an answer found on this site, which consists in activitating and stopping a ProgressDialog at the appropriate time (before and after findInBackground()).
startLoading(); //Show the loading image
query.findInBackground(new FindCallback() {
public void done(List<ParseObject> allQuestionsVal, ParseException e) {
if (e == null) {
for(int i = 0; i<=allQuestionsVal.size()-1;i++){
ParseObject questionVal = allQuestionsVal.get(i);
Question question = new Question(questionVal.getObjectId(),
questionVal.getString("FIELD1"),
questionVal.getString("FIELD2"),
allQuestions.add(question);
}
stopLoading(); //Remove the loading image
//Use the result of the Query (allQuestions) to populate listVIew
ListView list = (ListView) findViewById(R.id.all_questions);
AllQuestionsAdapter adapter=new AllQuestionsAdapter(AllQuestions.this, allQuestions);
list.setAdapter(adapter);
}
else {
stopLoading(); //Remove the loading image
}
}
});
protected ProgressDialog proDialog;
protected void startLoading() {
proDialog = new ProgressDialog(this);
proDialog.setMessage("loading...");
proDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
proDialog.setCancelable(false);
proDialog.show();
}
protected void stopLoading() {
proDialog.dismiss();
proDialog = null;
}
PS: any comments are welcomed :)
Related
I am a newbie here, and I have searched online (and on stackoverflow) for the answer but I am still struggling to make it work.
What I am trying to do, is (1) update my list with fresh "posts" using an asyncronous task - thus allowing the user to continue using the app as I download new posts to their android.
I am struggling to get the updating task to work, and it could be tied to an obvious implementation problem (or not).
What I have is (1) A customized list (it allows "pull to refresh" - but as stated it is a problem that it is not refreshing any data at this point). (2) a custom AsyncTask that will theoretically populate more posts for the main list on the main screen.
Here is problem point in the list:
listView.setOnRefreshListener(new PullToRefreshListView.OnRefreshListener(listView) {
#Override
public void onRefresh() {
mylistAdapter.loadNewData(); //loads new data <-------------------
m_ptrlistView.postDelayed(new Runnable() {
#Override
public void run() {
m_ptrlistView.onRefreshComplete();
}
}, 2000);
////////////
Here is the function "loadNewData" in the adapter
public void loadNewData(PullToRefreshListView List){
//load new stuff
new AsyncFetchMore(list).execute();
// MANDATORY: Notify that the data has changed
notifyDataSetChanged();
return;
}
And... my asyncTask that is extended's implementation
#Override
protected Object doInBackground() {
try {
//simulating a long task
Thread.sleep(5000);
} catch (InterruptedException e) {
Log.d("Notes", "Thread failed to sleep");
}
//create dummy posts for testing
for ( int i = 12; i < 24; i++ ) {
Post pNewPost = new Post();
pNewPost.setText("POST # " + i);
m_alNewPosts.add(pNewPost);
}
return null;
}
///////////////////////////////
Perhaps I'm approaching it all wrong. I'm having doubts... But I just don't know what the right next step is and I am pretty lost here! Can you give me any tips?
It looks like you arent doint anything with results that are returned by your async task. But before you go to fix it, please consider using Loaders - they are asyncronous and made specifically for your purpouse - getting data for Fragment/Activity. Here is documentation for them. It looks like you might have a fair amount of refactoring to do if you want to implement them, but its well worth it - its the right way. hope this helps.
You are calling notifyDataSetChanged() right after you start your Async thread, which hasn't populated your data. Call notifyDataSetChanged() after the data has been updated. Check out the examples in ApiDemos in the samples directory of the SDK.
Edit
After moving my loading / creation code to an Async Task (see below) - I still have the initial problems that I had with my original splashscreen.
Those being that:
1) On starting the Async task in onCreate, everything is loaded but my Dialog can only be shown when onStart() is called which makes the whole process kind of pointless as there is a long pause with a blank screen, then after everything has loaded, the 'loading' dialog flashes up for a split second before disappearing.
2) I can't move object loading / creation etc to onStart because a) it will be run again even when the app is resumed after being sent to the background which I don't want to happen, and b) when when calling restoring the savedInstanceState in onCreate() I'll get a nullPointerException because i'm restoring properties of objects that won't have yet been created.
Would really appreciate if someone could advise how to get around these problems and create a simple splashscreen. Thanks!
Background
My app uses only one activity and I would like to keep it that way if possible.
I've struggled with this for over a week so really hope someone can help me out.
All I want to do is use a splashscreen with a simple 'loading' message displayed on the screen while my resources load (and objects are created etc.) There are a couple of points:
Conditions
1) The splashscreen should not have it's own activity - everything needs to be contained in a single-activity
2) The splashscreen should not use an XML layout (I have created a Splashscreen class which uses View to display a loading PNG)
3) My app is openGL ES 2.0 so the textures need to be loaded on the OpenGL Thread (creation of objects etc that don't use GL calls are OK to go on another thread if necessary).
What I've attempted so far
What I did so far was to create a dialog and display it in my onStart() method with:
Dialog.show();
then let everything load in my onSurfaceCreated method before getting rid of it with:
Dialog.dismiss();
However I needed to change this for varioius reasons so now I create my objects from a call within my onCreate() method and just let the textures load in my GL Renderer's onSurfaceCreated method.
However, this means that because the dialogue isn't displayed until after onCreate, I still get a delay (blank screen) while everything is created before the splash-screen is shown, this then stays on the screen until the textures have loaded. There are other issues with this too which can wait for another day!
So my approach is obviouly very wrong. I read every tutorial I could and every splash-screen related question I could find on SO and Gamedev.SE but I still can't find an explanation (that makes sense to me), of how this can be achieved.
I'm hope someone here can explain.
You should be able to use AsyncTask to load resources in the background and then just dismiss your splash
Here's an AsyncTask that I use to load data from a remote db. This displays a loading progress circle until the task is complete but should be easily re-purposed to display your splash
AsyncTask that runs in the background
private class SyncList extends AsyncTask<Void, ULjException, Void> {
private static final String TAG = "SyncList";
private final class ViewHolder {
LinearLayout progress;
LinearLayout list;
}
private ViewHolder m;
/**
* Setup everything
*/
protected void onPreExecute() {
Log.d(TAG, "Preparing ASyncTask");
m = new ViewHolder();
m.progress = (LinearLayout) findViewById(R.id.linlaHeaderProgress);
m.list = (LinearLayout) findViewById(R.id.listContainer);
m.list.setVisibility(View.INVISIBLE); //Set the ListView that contains data invisible
m.progress.setVisibility(View.VISIBLE); //Set the loading circle visible you can sub in Dialog.show() here
}
/**
* Async execution performs the loading
*/
#Override
protected Void doInBackground(Void... arg0) {
try {
Log.d(TAG, "Syncing list in background");
dba.open(ListActivity.this);
dba.sync();
} catch (ULjException e) {
publishProgress(e);
}
return null;
}
/**
* Display exception toast on the UI thread
*/
protected void onProgressUpdate(ULjException... values) {
Log.e(TAG, values[0].getMessage());
Toast.makeText(ListActivity.this, "Sync failed", Toast.LENGTH_LONG).show();
}
/**
* Finish up
*/
protected void onPostExecute(Void result) {
Log.d(TAG, "ASyncTask completed, cleaning up and posting data");
fillData();
m.list.setVisibility(View.VISIBLE); //Show the list with data in it
m.progress.setVisibility(View.INVISIBLE); //Hide the loading circle sub in Dialog.dismiss()
}
}
Calling the Task
protected void onStart() {
super.onStart();
// Init the dba
dba = DBAccessor.getInstance();
new SyncList().execute();
}
It should be noted that the AsyncTask is an inner class of the Activity its related to here
Edit
onCreate Method
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
Dialog.show();
//This launches a new thread meaning execution will continue PAST this call
//to onStart and your loading will be done concurrently
//Make sure to not try to access anything that you're waiting to be loaded in onStart or onResume let your game start from onPostExectue
new AsyncTask.execute();
}
doInBackground
protected Void doInBackground(Void... arg0) {
Load all resources here
}
onPostExecute
protected void onPostExecute(Void result) {
Dialog.dismiss();
Call a method that starts your game logic using your newly loaded resources
}
I'm having a problem refresh the data in list view.
I get the data in the list from a server, and when I want to refresh the data I need to go to the server and receive the new data.
the notifyDataSetChanged() not helping and also the ListView.invalidateViews not helping.
when I rotate the device the list updated.
how can I load the list view in the same way the screen rotation do it?
This is the code on create that fill the list view.
thanks in advance.
query = new ParseQuery(PET_CLASS_NAME);
petListView.addHeaderView((View)getLayoutInflater().inflate(R.layout.header_row, null));
petDetailIntent = new Intent(getApplicationContext(), PetDetailActivity.class);
selectCityIntent = new Intent(this, CitiesActivity.class);
loadingIntent = new Intent(getApplicationContext(), LoadingActivity.class);
startActivityForResult(loadingIntent, LOADING_INTENT_CODE);
/*the user see list of pets that are still missing*/
query.whereEqualTo(PET_FOUNDED, false);
selectedCity = settings.getString("cityQuery", "");
if(selectedCity != ""){
query.whereEqualTo(PET_CITY, selectedCity);
}
query.findInBackground(new FindCallback() {
#Override
public void done(List<ParseObject> list, ParseException e) {
if (e == null) { //objects retrieved well
petList.addAll(list);
//MyAdapter
adapter = new MyAdapter(
getApplicationContext(),
android.R.layout.simple_list_item_1,
R.id.tv_pet_name,
petList);
setListAdapter(adapter);
}
else{
toaster(getResources().getString(R.string.error_message_load_pets));
finish();
}
finishActivity(LOADING_INTENT_CODE);
}
});
Use a AsyncTask for loadData from Server. It will load it faster.
Try this out:
private class YourTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... s) {
//Here you have to make the loading / parsing tasks
//Don't call any UI actions here. For example a Toast.show() this will couse Exceptions
// UI stuff you have to make in onPostExecute method
}
#Override
protected void onPreExecute() {
// This method will called during doInBackground is in process
// Here you can for example show a ProgressDialog
}
#Override
protected void onPostExecute(Long result) {
// onPostExecute is called when doInBackground finished
**// Here you can for example fill your Listview with the content loaded in doInBackground method**
}
}
And than you just have to call this AsyncTask always if you loading content from your server:
new YourTask().execute("");
Try it out!.. Hope this helps..
When you rotate the device, the activity is actually started stopped and started and your initial request will be made again.
You should place your request code into a method and recall it yourself
Similar to what Rawkode mentioned, it doesn't seem like the code that actually does the work of retrieving data from the server is reusable (since it lives in onCreate()). Take a look at this diagram: http://developer.android.com/images/activity_lifecycle.png. As you can can see, the onCreate() method only gets executed once, unless the Activity is re-created (i.e. rotating screen).
Also, from the given code, there doesn't seem to be evidence of a refresh method either. How will users be able to refresh the data? Consider refactoring your code such that the work is done in a method that you can call later on (i.e. refreshData()) and then figure out a way in which you would like your users to refresh. For example, you can use either the ActionBar with a refresh ActionItem, or a menu option or even a button.
I develop one application in Android. Which contains so many data (String) and images. string data are come from database and images comes from /res folder.
In My Application First Activity shows categories of books. Then i select any one of them then jump to the next activity which display all books images and brief description of selected category these all data are coming from database with Query operation and fill custom list view with ArrayAdapter. These is working and display all the things which i want.
but the problem is that when i click on category from one activity it takes more than 1 minute time to display second activity (Detail Information of Selected Category). So, Here user is stuck. It is bad for my application.
So is there any way to solve these or any Idea to display Activity Loading Process between One Activity to Second Activity ?
Thanks in Advance.
Please Help Me to solve these.
use AsyncTask as
public class My_Game_Task extends AsyncTask<String, Void, Void> {
#Override
protected void onPreExecute() {
//put a preloder
super.onPreExecute();
}
#Override
protected Void doInBackground(String... arg0) {
// TODO Auto-generated method stub
find data from database
return null;
}
#Override
protected void onPostExecute(Void result) {
dismiss preloader
set adapter here
super.onPostExecute(result);
}
}
call on
oncreate as new My_Game_Task().execute();
this will immediately show the next activity and will show a preloader
First of all where are you testing the app.. if its on emulator then check it on actual device you would get a idea how much delay takes place actually.!
I had similar problem it takes minutes on emulator but runs amazingly on actual device.It takes just 1 second to display..
Try this one it will make a delay of one second before going to execute any other operations,
try {
Thread.sleep(1000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
I work on a Battleships game as my first Android application.
I decided to use a ViewSwitcher that holds two GridViews. One bUserGrid is for the User field (hosting user ships), bComputerGrid is for the Computer field (showing user shots).
GridView bComputerGrid, bUserGrid, mComputerGrid, mUserGrid;
ViewSwitcher bigSwitcher, miniSwitcher;
User strikes (taps Computer field).The application runs the AsyncTask userAttack which defines whether that strike was successful or not.
bComputerGrid.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
runUserAttack(position);
}
});
If user missed, then in a onPostExecute() section of userAttack I call notifyDataSetChanged() in order to refresh the bComputerGrid.
protected void onPostExecute(String message) {
...
bComputerAdapter.notifyDataSetChanged();
mComputerAdapter.notifyDataSetChanged();
firstmateMsg.setText(message);
mUserBundle = mUserAttack.getmUBundle();
mUserAttack=null;
if (isCancelled()) return;
if (mUserBundle.getBoolean("userMissed")) {
mComputerAttack = new computerAttack();
mComputerAttack.execute(mComputerBundle);
} else {
if (doesWon(seqComputerShips)) {
showDialog(0);
}
}
}
But it doesn’t happen! Following statement doesn’t update bComputerGrid, if user misses.
bComputerAdapter.notifyDataSetChanged();
Then here in onPostExecute() section of userAttack I start AsyncTask computerAttack. In onPreExecute() section of computerAttack I switch bComputerGrid to bUserGrid by calling
bigSwitcher.showNext();
Switching happens but bComputerGrid hasn't been updated before that!
Computer does its strike and successfully refreshes the user field in onProgressUpdate() section of computerAttack by calling bUserAdapter.notifyDataSetChanged(). When Computer missed, the application comes to wait for the user strike (tap) again.
protected void onProgressUpdate(String... messages) {
...
mUserAdapter.notifyDataSetChanged();
bUserAdapter.notifyDataSetChanged();
}
protected void onPostExecute(Boolean result) {
mComputerBundle = mComputerAttack.getmCBundle();
mComputerAttack=null;
if (field_switch) {
switchViews();
}
}
But why I can’t refresh bComputerGrid before that switching and Computer shot happens?
Could you, please, help me?
Where you update your adapters? You change underlying data of the adapter, or you change the adapter list?
Adapters are also part of the UI, so changes of the adapter itself should happen only in a GUI thread. I got a couple of UI Exceptions (on display) telling me so in some other project as I changed the adapter contents in a Service Thread.
Eventually you have to recreate your adapter list to reflect changes in underlying data?