Start something when Listview is filled - android

I have a ListView which displays images from my cloud.
There may be a delay between when my user open the activity with the ListView and when the ListView is populated with the images.
For example if the user do not have the Internet connection on, the images won't be displayed.
I'd like to change several things on my UI (add a button, start an animation...) only when the ListView is filled. I guess I should use a listener to know when the ListView is not empty or when my EmptyView visibility is gone. Here are the two solutions I tried :
Solution 1:
myListview.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
#Override
public void onSystemUiVisibilityChange(int i) {
if (myListview.getVisibility() == View.VISIBLE){
//UI changes here
Solution 2 :
if (listviewAdapter != null){
...UI changes here
None of these solutions work, and I cannot find another one. Any idea ?
Thank you !

You can set a timer for this approach. For example wait for 5 seconds or 10 seconds and check if the listView is populated or not if yes then show what ever you want else do not show.
final Timer timer2 = new Timer();
timer2.schedule(new TimerTask() {
public void run() {
if(listViewCount>0)
{
//do your stuff
}
}
}, 5000);

Use AsyncTask class like this:
...
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
if(checkConnexion()){ showToast("No Connexion"); }
else{ new loadImage().execute(); }
}
class loadImage extends AsyncTask<Void, Void, Void> {
ProgressDialog dialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
/* show ProgressDialog before doing anything*/
dialog = ProgressDialog.show(getApplicationContext(), "Veuillez patienter", "Chargement des données....", true);
}
#Override
protected Void doInBackground(Void... param) {
try {
/* load your images into ArrayList for example */
} catch (Exception e) {
e.printStackTrace();
dialog.dismiss();
}
return null;
}
#Override
protected void onPostExecute(Void res) {
/* ** Update your UI here ***
if size of ArrayList >0 initial your adapter
listView.setAdapter(adapter);
else showToast("Erreur loading ...");
****hide ProgressDialog after finishing*** */
dialog.dismiss();
}}
private void showToast(String msg){Toast.makeText(getApplicationContext(),msg, Toast.LENGTH_SHORT).show();}

Related

ChrisBanes PullToRefresh 'Loading...' issue

I am using PullToRefresh ListView from chrisbanes which I found here.
I implemented it successfully, thanks to its documentations. :)
However, I am stuck at this one point now. I am using volley to get the data from the server. It works perfectly till I added a check to see if theres no more data then simply Toast the user.
I did like below,
#Override
public void onRefresh(
PullToRefreshBase<ListView> refreshView) {
if (hasMoreData()){
//Call service when pulled to refresh
orderService();
} else{
// Call onRefreshComplete when the list has been refreshed.
toastShort("No more data to load");
orderListAdapter.notifyDataSetChanged();
mPullRefreshListView.onRefreshComplete();
}
}
The toast comes up, but I also continue seeing the Loading... message below my ListView. I thought onRefreshComplete(); should take care of it but it didn't.
How do I do this? Please help.
After banging my head for almost 3hours I was able to solve this. It was quite simple tough.
What I did was created a Handler and a Runnable which calls mPullRefreshListView.onRefreshComplete(); and checked after some time that if mPullRefreshListView was still refreshing then call the method again which closes it on the next call. :)
Code goes like this..
#Override
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
if (hasMoreData()) {
// Call service when pulled to refresh
toastShort("Last");
orderService();
} else {
// Call onRefreshComplete when the list has been
// refreshed.
toastShort("No more data to load");
upDatePull(); //this method does the trick
}
}
private void upDatePull() {
// lvOrders.setAdapter(null);
handler = new Handler();
handler.postDelayed(runnable, 1000);
}
Runnable runnable = new Runnable() {
#Override
public void run() {
mPullRefreshListView.onRefreshComplete();
if (mPullRefreshListView.isRefreshing()) {
Logger.d("xxx", "trying to hide refresh");
handler.postDelayed(this, 1000);
}
}
};
Credits to this link.
you should use onRefreshComplete(); in a separate thread like:
#Override
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
if (hasMoreData()){
//Call service when pulled to refresh
orderService();
} else{
toastShort("No more data to load");
orderListAdapter.notifyDataSetChanged();
}
new GetDataTask(refreshView).execute();
}
public class GetDataTask extends AsyncTask<Void, Void, Void> {
PullToRefreshBase<?> mRefreshedView;
public GetDataTask(PullToRefreshBase<?> refreshedView) {
mRefreshedView = refreshedView;
}
#Override
protected Void doInBackground(Void... params) {
// Do whatever You want here
return null;
}
#Override
protected void onPostExecute(Void result) {
mRefreshedView.onRefreshComplete();
super.onPostExecute(result);
}
}

How do I set up my doInBackground's params in my AsyncTask?

my screen when I click on a button is slow to load (because of downloading images? the image files are really small though) so I tried to use AsyncTask to help. The program works, but I moved the image loading to an AsyncTask to see if it would load faster and the app crashes every time. I'm guessing it has to do with the way I have it set up. How would I fix it? Would using a runnable thread be better instead? Thanks!
The class:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// no title
requestWindowFeature(Window.FEATURE_NO_TITLE);
// set full screen
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// inflate listview
setContentView(R.layout.gmg);
**new Load.execute(); // executes AsyncTask**
...
gmgListView = (ListView) findViewById(R.id.gmg_list2);
GMGListViewAdapter adapter = new GMGListViewAdapter(this,
R.layout.gmg_list_row, rowItems);
gmgListView.setAdapter(adapter);
gmgListView.setOnItemClickListener(this);
}
The AsyncTask:
private class Load extends AsyncTask<String, Void, Void> {
private ProgressDialog Dialog = new ProgressDialog(GMGListViewActivity.this);
#Override
protected void onPreExecute() {
Dialog.setMessage("Doing something...");
Dialog.show();
}
#Override
protected Void doInBackground(String... params) {
SparseArray<Spanned> gmgText = null;
Integer[] right = null;
SparseArray<Drawable> appIcon = null;
try {
gmgText = ParseContent.queryGMGText();
right = ParseContent.queryGMGRight();
appIcon = ParseContent.queryDrawable();
} catch (ParseException e) {
e.printStackTrace();
}
// Inflate GMG's rows
rowItems = new ArrayList<GMGRowItem>();
for (int i = 0; i < gmgText.size(); i++) {
GMGRowItem item = new GMGRowItem(appIcon.get(i), gmgText.get(i), right[i]);
rowItems.add(item);
}
return null;
}
protected void onPostExecute(Void unused) {
Dialog.dismiss();
}
}
You need to apply some changes in your code like...
need to set list adapter in onPostExecute method and remove it from onCreate().
After completing background process it will interact with ui thread.
protected void onPostExecute(Void unused) {
Dialog.dismiss();
GMGListViewAdapter adapter = new GMGListViewAdapter(this,
R.layout.gmg_list_row, rowItems);
gmgListView.setAdapter(adapter);
}
Try this and let me know if you got any isssue.

How to set adapter of spinner by using Async Task Class

In my code I load a spinner adapter by using Async Task
In My case The ProgressDialog is Not dismissing
This is My code.
I want to show the item after adapter load and the progressDialog is to dismiss
Please Help me, Thanks
private class LoadMoreVehicals extends AsyncTask<Object, Integer, Object> {
#Override
protected void onPreExecute() {
progressBar = ProgressDialog.show(RegistrationScreen.this, "",
"Loading...");
progressBar.setIndeterminate(true);
progressBar.setIndeterminateDrawable(getResources().getDrawable(
R.anim.progressbar_handler));
super.onPreExecute();
}
#Override
protected Object doInBackground(Object... params) {
String countryUrl = ConstantURL.COUNTRY_URL;
getCounty(countryUrl);
countrySpinner
.setAdapter(new MyCustomSpinnerAdapter(
RegistrationScreen.this,
R.layout.spinner_dropdown,
countyList));
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
progressBar.getProgress();
}
#Override
protected void onPostExecute(Object result) {
progressBar.dismiss();
Log.e("Im in onPostExecute", "");
super.onPostExecute(result);
}
}
While programming in Android you should remember one thing that any task which draws something on the screen should be executed on the main thread. When you set the adapter then android calls the getView() method of the adapter and draws views on the screen. So you should set the adapter in the postExecute() method instead in doInBackground() method.
Here is a small sample to clear my point:
class MyTask extends AsyncTask<Void, Void, Void> {
ProgressDialog pd = new ProgressDialog(MainActivity.this);
#Override
protected void onPreExecute ( )
{
//starting the progress dialogue
pd.show();
}
#Override
protected Void doInBackground (Void... params)
{
//fetch data here
...
...
return null;
}
#Override
protected void onPostExecute (Void result)
{
//set adapter here
...
...
//dismissing the progress dialogue
pd.dismiss();
}
}
In my experience i have so many problems with async runs and UI so now always separate the stuff trying to place the "responsibilities" in each place. So i do something like this:
Create my Async class with the process i want to do and nothing that transform the UI in it
Create a function in UI thread that modify the UI when async task finish, something like OnAsyncTaskComplete(Object response)
Keep communicated the threads
public class MyActivity extends Activity {
private static MyAsyncClass backgroundTask;
private static ProgressDialog pleaseWaitDialog;
//......activity stuff.......
#Override
public void onPause()
{
super.onPause();
//Get rid of progress dialog in the event of a screen rotation or other state change. Prevents a crash.
if (pleaseWaitDialog != null)
pleaseWaitDialog.dismiss();
}
//Function to avoid lose the async thread if the app interrupts (phone rotation, incoming call, etc) RECOMENDED TO HANDLE THIS!!
//Sets the current state after app resume
#Override
public void onResume()
{
super.onResume();
//If there is a background task set it to the new activity
if ((backgroundTask != null) && (backgroundTask.getStatus() == Status.RUNNING))
{
if (pleaseWaitDialog != null)
pleaseWaitDialog.show();
backgroundTask.setActivity(this);
}
}
}
//Logic business after the web service complete here
//Do the thing that modify the UI in a function like this
private void onTaskCompleted(Object _response)
{
//For example _response can be a new adapter
MyList.setAdapter((BaseAdapter)_response);
//or can be a list to create the new adapter
MyList.setAdapter(new MyAdapter(this, (ArrayList<String>)_response));
//or can be anything you want, just try to make here the things that you need to change the UI
}
/**
* Class that handle the async task
*/
public class MyAsyncClass extends AsyncTask<Void, Void, Object>
{
//Maintain attached activity for states change propose
private MyActivity activity;
//Keep the response of the async task
private Object _response;
//Flag that keep async task completed status
private boolean completed;
//Constructor
private MyAsyncClass(MyActivity activity) {
this.activity = activity;
}
//Pre execution actions
#Override
protected void onPreExecute() {
//Start the splash screen dialog
if (pleaseWaitDialog == null)
pleaseWaitDialog= ProgressDialog.show(activity.this,
"PLEASE WAIT",
"Getting results...",
false);
}
//Execution of the async task
protected Object doInBackground(Object...params)
{
//return the thing you want or do want you want
return new ArrayList();
}
//Post execution actions
#Override
protected void onPostExecute(Object response)
{
//Set task completed and notify the activity
completed = true;
_response = response;
notifyActivityTaskCompleted();
//Close the splash screen
if (pleaseWaitDialog != null)
{
pleaseWaitDialog.dismiss();
pleaseWaitDialog = null;
}
}
//Notify activity of async task completion
private void notifyActivityTaskCompleted()
{
if ( null != activity ) {
activity.onTaskCompleted(_response);
}
}
//for maintain attached the async task to the activity in phone states changes
//Sets the current activity to the async task
public void setActivity(MyActivity activity)
{
this.activity = activity;
if ( completed ) {
notifyActivityTaskCompleted();
}
}
}
}
Hope its help you
First of all you cannot set the adapter in the doInBackground
follow this design:
private class LoadMoreVehicals extends AsyncTask<Object, Integer, Object>
{
private ArrayList<Country> countries;
#Override
protected void onPreExecute() {
progressBar = ProgressDialog.show(RegistrationScreen.this, "","Loading...");
progressBar.setIndeterminate(true);
progressBar.setIndeterminateDrawable(getResources().getDrawable(R.anim.progressbar_handler));
super.onPreExecute();
}
#Override
protected Object doInBackground(Object... params) {
String countryUrl = ConstantURL.COUNTRY_URL;
countries = getCounty(countryUrl);
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
progressBar.getProgress();
}
#Override
protected void onPostExecute(Object result) {
countrySpinner.setAdapter(new MyCustomSpinnerAdapter(RegistrationScreen.this,R.layout.spinner_dropdown,countries));
progressBar.dismiss();
Log.e("Im in onPostExecute", "");
super.onPostExecute(result);
}
}

ProgressDialog not shown in AsyncTask

I have a huge database (40MB) on an SDCard. I need fetch data, with LIKE in query, which is very slow.
DB request takes about 5 seconds. Therefore, I need to do it asynchronously and with ProgressDialog.
I tried it with AsyncTask, but problem is with ProgressDialog. It was implemented this way:
private class GetDataFromLangDB extends AsyncTask<String, String, String> {
private final ProgressDialog dialog = new ProgressDialog(TranslAndActivity.this);
#Override
protected void onPreExecute() {
super.onPreExecute();
urDBCursor.close();
curDBCursor = null;
scaAdapter = null;
this.dialog.setMessage("Loading data...");
this.dialog.show();
}
#Override
protected String doInBackground(String... whatSearch) {
String result = "";
if (myDatabaseAdapter != null) {
curDBCursor = myDatabaseAdapter.fetchAll(whatSearch[0]);
}
return result;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
prepareListView();
}
}
The problem is that ProgressDialog is not shown during the DB request.
After finished database query, it flash on screen for a short time. When user tries
to tap on screen during database request, UI is freezed, and after DB request
message about 'not responding' is shown.
I tried it with a thread this way:
public void startProgress(View view, final String aWhatSearch) {
final ProgressDialog dialog = new ProgressDialog(MyActivity.this);
if (curDBCursor != null){
curDBCursor.close();
curDBCursor = null;
}
dialog.setMessage("Loading data...");
dialog.show();
Runnable runnable = new Runnable() {
public void run() {
curDBCursor = myDatabaseAdapter.fetchAll(aWhatSearch);
// dirty trick
try {
Thread.sleep(250); // it must be here to show progress
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
public void run() {
if (dialog.isShowing()) {
dialog.dismiss();
}
prepareListView();
}
});
}
};
new Thread(runnable).start();
}
The result was the same, but when I used the trick with Thread.sleep(250);
ProgressDialog was shown during the database request. But it is not spinning,
it looks freezed during the DB request.
DB stuff is called this way (after tap on search button):
btnSearchAll.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// AsyncTask
new GetDataFromLangDB().execute(edtTextToSearch.getText().toString());
// or Thread
//startProgress(null, edtTextToSearch.getText().toString());
}
});
I found a lot of problems like this in SO, but nothing was useful for me.
Could it be that DB is on SD Card?
I put the definition of the dialog into the AsyncTask Class and it works fine for me.
Take a look at this exampel (You have to change NAMEOFCLASS in the name of your CLASS:
private class doInBackground extends AsyncTask<Integer, Integer, Void> {
final ProgressDialog dialog = new ProgressDialog(NAMEOFCLASS.this) {
#Override
protected void onPreExecute() {
dialog.setCancelable(false);
dialog.setTitle(getString(R.string.daten_wait_titel));
dialog.setIcon(R.drawable.icon);
dialog.setMessage(getString(R.string.dse_dialog_speichern));
dialog.show();
}
#Override
protected void onCancelled() {
dialog.cancel();
}
....
#Override
protected void onProgressUpdate(Integer... values) {
// DO YOUR UPDATE HERE
}
#Override
protected void onPostExecute(Void result) {
dialog.dismiss();
}
}
Maybe this SO answer could help you. It looks like similar problem. Try to use AsyncQueryHandler for querying your database
declare you Dialog box on Class (Activity) level like this
private ProgressDialog dialog = null;
show the progress dialog and call the AsyncTask class when you want to start you Busy work..like onButton click or any
dialog = ProgressDialog.show(this,"Sending Email to your account please! wait...", true);
SendingEmailTask task = new SendingEmailTask();
String s = "";
task.execute(s);
create your inner class like
private class SendingEmailTask extends AsyncTask<String, Void, String> {
protected String doInBackground(String... urls) {
//do your work here..
// like fetching the Data from DB or any
return null;
}
#Override
protected void onPostExecute(String str) {
//hide progress dialog here
dialog.dismiss();
}
}
let me know if this help!!

How can I run my function in a thread in android?

I have a function that dynamically creates all my user interface.
What can I do to show a dialog progress while my function is executing, and then dismiss the dialog when my function has finished the user interface?
This is an example of my code:
Sorry, I'm new to android, it is hard for me to understand some code... I will write my code here...
I have this function:
public void principal() {
//CODE TO CREATE ALL THE USER INTERFACE DYNAMICALLY
}
and I have the asyncTask like this:
public class EjecutarTarea extends AsyncTask<Void, Void, Void>
{
protected void onPreExecute() {
dialog = new ProgressDialog(StadioNenaActivity.this);
dialog.setMessage("Cargando..");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
protected Void doInBackground(Void... unused) {
Principal();
return null;
}
#Override
protected void onProgressUpdate(Void... unused) {
}
#Override
protected void onPostExecute(Void unused) {
dialog.dismiss();
}
}
When I execute the asynctask in the onCreate, it crashes:
new EjecutarTarea().execute();
Use an AsyncTask. It gives a fantastic and easy way to load stuff in the background and them paste views in the main thread.
Here is an example of my AsyncTask:
private class LoadingTask extends AsyncTask<Void, Integer, Void> {
private ProgressBar mProg;
private TextView mLoadingText;
#Override protected void onPreExecute() {
mProg = (ProgressBar)findViewById(R.id.launcherbar_loadprogress);
mProg.setTouchDelegate(null);
mProg.setClickable(false);
mProg.setLongClickable(false);
mProg.setOnTouchListener(null);
mProg.setMax(100);
mLoadingText = (TextView) findViewById(R.id.launcheractivity_loadingwhat);
}
#Override protected Void doInBackground(Void... voids) {
try { Thread.sleep(1000); } catch (InterruptedException e) { }
setProgressAndSleep(R.string.loading_log, 29, 250);
LOG.setContext(LauncherActivity.this);
LOG.setDebug(true);
setProgressAndSleep(R.string.loading_database, 43, 250);
AppionDatabase.setContext(LauncherActivity.this);
setProgressAndSleep(R.string.loading_sensors, 57, 250);
Sensor.init(LauncherActivity.this);
setProgressAndSleep(R.string.loading_jobs, 71, 250);
Job.init(LauncherActivity.this);
setProgressAndSleep(R.string.loading_workbenches, 86, 250);
WorkbenchState.init(LauncherActivity.this);
setProgressAndSleep(R.string.loading_application_state, 100, 250);
ApplicationState.setContext(LauncherActivity.this);
startService(new Intent(LauncherActivity.this, BluetoothConnectionService.class));
return null;
}
#Override public void onProgressUpdate(Integer... prog) {
mLoadingText.setText(prog[0]);
mProg.setProgress(prog[1]);
}
#Override public void onPostExecute(Void voids) {
startActivity(new Intent(LauncherActivity.this, HomescreenActivity.class));
}
private void setProgressAndSleep(int text, int progress, int duration) {
try {
publishProgress(new Integer[] {text, progress});
Thread.sleep(duration);
} catch (InterruptedException e) {
LOG.e(TAG, "Failed to sleep thread while loading Application Contexts!", e);
}
}
}
Edit NOTE I recommend not keeping the setProgressAndSleep(int, int int) method. I only use it cause it loads too fast and I really wanted the loading bar. :-P
All changes in Android UI will makes in UI Thread. To run your function in UI thread you need to use mathos runOnUIThread() from activity http://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)
Hope it help you!
Your best shot is, probably, to use ViewSwitcher to have temporary view with progress bar while you construct other view. Do operations that take time in doInBackground() of AsyncTask but actual operations on UI such as flipping the view must be done in postExecute() or via runOnUIThread(). Progress updates may be done in onProgressUpdate()

Categories

Resources