I have some tabpages and fragments. And these fragments contain a GridView element. My program is going to webservice and reading JSON data, after getting images caching and populating gridviews custom grid.
Now, how can show ProgressDialog only not completed fragments? And how can I dismiss progressDialog GridView populating will complete?
My Fragment OnCreate Method;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_b, container, false);
context = getActivity();
final ProgressDialog dialog = ProgressDialog.show(context, "", "Please wait, Loading Page...", true);
GridView gridView = (GridView) v.findViewById(R.id.gridview);
if (isConnected()) {
try {
new ProgressTask(context).execute();
gridView.setAdapter(new AdapterB(context, WallPaperList));
} catch (NullPointerException e) {
e.printStackTrace();
return v;
}
} else {
Toast.makeText(v.getContext(), "Please check your internet connection..!", Toast.LENGTH_LONG).show();
}
return v;
}
its the short example for showing progress may this help you
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = ProgressDialog.show(DownloadImageActivity.this, "Wait", "Downloading...");
}
#Override
protected Bitmap doInBackground(String... params) {
//your downloading code
}
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(Bitmap bitmap) {
progressDialog.dismiss();
}
}
Check this...........
public interface AsyncTaskListener<Boolean> {
public void onCompletingTask(Boolean result);
}
public class AsyncTaskGetApiKey extends AsyncTask<Void, Void, Boolean>{
ArrayList<AsyncTaskListener<Boolean>> listeners;
public AsyncTaskLoadingInSplash() {
listeners = new ArrayList<AsyncTaskListener<Boolean>>();
}
public void addListener(AsyncTaskListener<Boolean> listener){
listeners.add(listener);
}
public void removeListener(AsyncTaskListener<Boolean> listener){
listeners.remove(listener);
}
#Override
protected Boolean doInBackground(Void... params) {
//do your activities here
return true; // If everything is fine
}
#Override
protected void onPostExecute(Boolean result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
for (AsyncTaskListener<Boolean> listener:listeners) {
listener.onReceivingApiKey(result);
}
}
}
public class MyFagemnt extends Fragment
implements AsyncTaskListener<Boolean>{
AsyncTaskGetApiKey task;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//......
task = new AsyncTaskGetApiKey();
task.addListener(this);
//........
}
#Override
public void onCompletingTask(Boolean result) {
// your asyntask finished
// now close the progress bar
}
}
In AsyncTask, create progress dialog in onPreExecute() and dismiss that progress dialog in onPostExecute().
updated:
add this code in your viewpager activity.
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
//You can get Call back to show the progress dialog when swipping.
boolean isLoading = true;//Check if the fragment is still loading or not at given position.
if (isLoading) {
//Show progress dialog.
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
Related
I have a progress dialog that shows how many files are left for uploading in my Async Task and the user can dismiss this dialog if he wants to. However I want to have a button that will be able to show again that progress dialog at its current stage and I don't know how to do that since you I can't just create a function in the Async Task and call it from a different activity. Any thoughts?
You can make a singleton class to handle the Async Task progress which holds only one listener (the Activity who wants to listen for the progress of your AsyncTask).
Your Singleton class can be like below:
public class ProgressDialogUtil {
public interface ProgressDialogUtilListener{
void showProgressDialog();
void dismissProgressDialog();
void updateProgressDialog(int value);
void setProgressDialogMessage(String message);
}
private ProgressDialogUtilListener listener;
private static ProgressDialogUtil mInstance;
public static ProgressDialogUtil getInstance() {
if (mInstance == null) {
synchronized (ProgressDialogUtil.class) {
if (mInstance == null) {
mInstance = new ProgressDialogUtil();
}
}
}
return mInstance;
}
public void setListener(ProgressDialogUtilListener listener) {
this.listener = listener;
}
public void showProgressDialog(){
if(listener!=null)
listener.showProgressDialog();
}
public void dismissProgressDialog(){
if(listener!=null)
listener.dismissProgressDialog();
}
public void updateProgressDialog(int value){
setProgressDialogMessage("Files Downloaded: "+ value);
if(listener!=null)
listener.updateProgressDialog(value);
}
public void setProgressDialogMessage(String message){
if(listener!=null)
listener.setProgressDialogMessage(message);
}
}
Then you can use this Singleton class (ProgressDialogUtil) in your AsyncTask like below to inform for any update occurred:
public class MyAsyncTask extends AsyncTask<Void, Integer, Boolean> {
public final ProgressDialogUtil progressDialogUtil;
public MyAsyncTask(ProgressDialogUtil progressDialogUtil){
this.progressDialogUtil = progressDialogUtil;
}
#MainThread
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialogUtil.setProgressDialogMessage("Start Download files..");
progressDialogUtil.showProgressDialog();
}
#WorkerThread
#Override
protected Boolean doInBackground(Void... params) {
//download your files here in the Background Thread...
//below is a sample loop
for (int i=0; i <= 50; i++) {
try {
Thread.sleep(1000);
publishProgress(i);
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
}
return true;
}
#MainThread
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressDialogUtil.updateProgressDialog(values[0]);
}
#MainThread
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
progressDialogUtil.setProgressDialogMessage("Finished Download!");
progressDialogUtil.dismissProgressDialog();
}
}
Then in your first Activity where you start the AsyncTask you can create a new instance of your Progress Dialog and set a listener ProgressDialogUtilListener to listen for any AsyncTask progress to show/hide/update the Progress Dialog like below:
ProgressDialog pd = new ProgressDialog(this);
ProgressDialogUtil progressDialogUtil = ProgressDialogUtil.getInstance();
progressDialogUtil.setListener(new ProgressDialogUtil.ProgressDialogUtilListener()
{
#Override
public void showProgressDialog() {
if (!pd.isShowing())
pd.show();
}
#Override
public void dismissProgressDialog() {
if (pd.isShowing())
pd.dismiss();
}
#Override
public void updateProgressDialog(int value) {
pd.setProgress(value);
}
#Override
public void setProgressDialogMessage(String message) {
pd.setMessage(message);
}
});
new MyAsyncTask(progressDialogUtil).execute();
Finally when you navigate to a new Activity you can use the same Singleton Instance ProgressDialogUtil and change the listener to the new Activity now all AsyncTask events will be handled to the new Activity and the dialog can be opened/closed via a button through this singleton class like below:
ProgressDialog pd = new ProgressDialog(this);
ProgressDialogUtil progressDialogUtil = ProgressDialogUtil.getInstance();
progressDialogUtil.setListener(new ProgressDialogUtil.ProgressDialogUtilListener()
{
#Override
public void showProgressDialog() {
if (!pd.isShowing())
pd.show();
}
#Override
public void dismissProgressDialog() {
if (pd.isShowing())
pd.dismiss();
}
#Override
public void updateProgressDialog(int value) {
pd.setProgress(value);
}
#Override
public void setProgressDialogMessage(String message) {
pd.setMessage(message);
}
});
//Show Progress Dialog from a Button Click
showButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
progressDialogUtil.showProgressDialog();
}
});
//Dismiss Progress Dialog from a Button Click
dismissButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
progressDialogUtil.dismissProgressDialog();
}
});
You can have a Live data in any singleton class like below to share the progress between activities.
object ProgressHelper {
val progress = MutableLiveData<Int>()
}
Then update the progress values from the AsyncTask like below:
override fun onProgressUpdate(vararg values: Int?) {
super.onProgressUpdate(*values)
ProgressHelper.progress.value = 100
}
In your activity you can observe the progress like below:
ProgressHelper.progress.observe(this, Observer {
val progress = it
})
In My Android Project I am using TabLayout,I have
Fragment1 --> Fragment2(AlertDialog)
|
button1--- name:
listview Id:
okButton--->AsyncTask
Here,In Fragment1 after pressing button1 calls another fragment(Fragment2), there after fillup the form pressing okbutton calls AsyncTask to receive data from server.then the data needs to display in Fragment1's
listview
My classes:
interface
public interface TaskCompleted {
// Define data you like to return from AysncTask
public void onTaskComplete(Integer result);
}
Fragment1
public class Fragment1 extends Fragment implements TaskCompleted {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_one, container, false);
btn1 = (Button) view.findViewById(R.id.button1);
listview = (ListView) view.findViewById(R.id.listview);
btn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DialogFragment picker = new SearchFragment();
picker.show(getActivity().getFragmentManager(), "dialog");
}
});
return view;
}
public static void submit(final String serverResponse) {
#SuppressWarnings("unused")
final class DownloadJSON extends AsyncTask<String, String, Void> {
#Override
protected Void doInBackground(String... params) {
try {
//code to process response
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void args) {
//display into adapter
}
}
}
}
Fragment2
public class Fragment2 extends DialogFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View content = inflater.inflate(R.layout.dialog_fragment, null);
builder.setView(content);
builder.setMessage("form")
// Positive button
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
new JSONfunctions(getActivity()).execute();
}
});
// Create the AlertDialog object and return it
return builder.create();
}
#Override
public void onTaskComplete(String serverResponse) {
// TODO Auto-generated method stub
}}
AsyncTask
public class JSONfunctions extends AsyncTask<String, String, String> {
private TaskCompleted mCallback;
public JSONfunctions(Context context){
this.mContext = context;
this.mCallback = (TaskCompleted) context;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
mProgressDialog = new ProgressDialog(mContext);
mProgressDialog.setIndeterminate(false);
mProgressDialog.show();
}
#Override
protected String doInBackground(String... params) {
String serverResponse="";
try {
====code to connect to server===
return serverResponse; (return result)
}
} catch (Exception e) {
e.printStackTrace();
}
return serverResponse;
}
#Override
protected void onPostExecute(String result) {
mProgressDialog.dismiss();
mCallback.onTaskComplete(result);
}
}
and in MainActivity I also have
#Override
public void onTaskComplete(String serverResponse) {
Fragment2.submit(serverResponse);
}
With this code from fragment2 after pressing okbutton it calls asyncTask
and gets successfull response from server..but not displaying into listview..Why?????
Such a complex scenario implemented for such a simple task.
All you need to do is let the Fragment1 implement TaskCompleted interface and create AsyncTask in a separate class and make an attribute of TaskCompleted in this task.
When in onPostExecute just call the listener function and one thing more you have to pass the fragment reference to your async task while creating its object in constructor.
final class DownloadJSON extends AsyncTask<String, String, Void> {
//your attributes
TaskCompleted listener;
public DownloadJSON(TaskCompleted listener){
this.listener = listener;
}
#Override
protected Void doInBackground(String... params) {
try {
jsonarray = new JSONArray(serverResponse);
Gson gson = new Gson();
User[] user = gson.fromJson(jsonarray.toString(), User[].class);
// Contact con = new Contact();
for (int i = 0; i < user.length; i++) {
HashMap<String, String> map = new HashMap<String, String>();
map.put("name", user[i].getFullname());
map.put("id", user[i].getId());
// Set the JSON Objects into the array
arraylist.add(map);
}
} catch (JSONException e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void args) {
listener.onTaskCompleted(arraylist);
}
}
public class Fragment1 extends Fragment implements TaskCompleted {
#Override
public void onTaskComplete(ArraList<YourListModel> data) {
adapter = new ListViewAdapter(activity, data);
// Set the adapter to the ListView
listview.setAdapter(adapter);
}
}
Also apply null checks where necessary.
I have an android project and I want to handle the back button in the fragment when I use the webview. When I use the webView and click on more than one link and then I click on back. It closes the application. How can I make it go to the back page. So far, I have done the followings :
public class NewsFragment extends Fragment {
private ProgressDialog progressDialog;
private WebView myWebView ;
public NewsFragment()
{
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_news, container, false);
myWebView = (WebView) rootView.findViewById(R.id.mwl_Website);
myWebView.setWebViewClient(new WebViewClient());
myWebView.getSettings().setBuiltInZoomControls(true);
myWebView.requestFocusFromTouch();
myWebView.setVerticalScrollBarEnabled(true);
myWebView.setHorizontalScrollBarEnabled(true);
myWebView.setVerticalScrollBarEnabled(true);
myWebView.setHorizontalScrollBarEnabled(true);
myWebView.requestFocusFromTouch();
myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.getSettings().setUseWideViewPort(true);
myWebView.getSettings().setLoadWithOverviewMode(true);
myWebView.addJavascriptInterface(new WebAppInterface(getActivity()), "Android");
myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.loadUrl(getResources().getString(R.string.WEBSITE));
new LoadViewTask().execute();
rootView.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == android.view.KeyEvent.ACTION_DOWN) {
if ((keyCode == android.view.KeyEvent.KEYCODE_BACK)) {
if(myWebView!=null)
{
if(myWebView.canGoBack())
{
myWebView.goBack();
}
}
}
}
return true;
}
});
return rootView;
}
private class LoadViewTask extends AsyncTask<Void, Integer, Void>
{
//Before running code in separate thread
#Override
protected void onPreExecute()
{
progressDialog = ProgressDialog.show(getActivity(),"Loading...",
"Loading please wait...", false, false);
}
//The code to be executed in a background thread.
#Override
protected Void doInBackground(Void... params)
{
/* This is just a code that delays the thread execution 4 times,
* during 850 milliseconds and updates the current progress. This
* is where the code that is going to be executed on a background
* thread must be placed.
*/
try
{
//Get the current thread's token
synchronized (this)
{
//Initialize an integer (that will act as a counter) to zero
int counter = 0;
//While the counter is smaller than four
while(counter <= 4)
{
//Wait 850 milliseconds
this.wait(1000);
//Increment the counter
counter++;
//Set the current progress.
//This value is going to be passed to the onProgressUpdate() method.
publishProgress(counter*25);
}
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
return null;
}
//Update the progress
#Override
protected void onProgressUpdate(Integer... values)
{
//set the current progress of the progress dialog
progressDialog.setProgress(values[0]);
}
//after executing the code in the thread
#Override
protected void onPostExecute(Void result)
{
//close the progress dialog
progressDialog.dismiss();
}
}
Problem you are facing is that your onBackPressed() is getting called, and you need to override that -
like this -
#Override
public void onBackPressed() {
if(myWebView!=null) {
if (webView.canGoBack()) {
webView.goBack();
}
}
super.onBackPressed();
}
Ref
I use a class which extends DialogFragment, and in this class I use an AsyncTask for loading the content of my AlertDialog.
My question is: how I can create an AlertDialog which shows: "Loading..." and then shows the content in my onPostExecute method?
public class MyDialog extends DialogFragment {
public MyDialog(){
super();
}
#Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
....
return builder.create();
}
public class myTask extends Asynctask<Void, Void, Void> {
#Override
protected Void onPreExecute(){
Show loading... in AlertDialog
}
#Override
protected Void doInBackground(Void... voids) {
Load content...
}
#Override
protected Void onPostExecute(){
Show content in AlertDialog
}
}
For that purpose, my suggestion is that don't use AlertDialog. Use a progress dialog, Here is your complete dialog,
public class MyDialog extends DialogFragment {
public MyDialog(){
super();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.your_dialog_id, container, false);
new myTask().execute();
return view;
}
private void afterContentLoad (Object content)
{
//Update your UI with respect of your content :)
}
public class myTask extends Asynctask<Void, Void, Void> {
private ProgressDialog mDialog;
#Override
protected Void onPreExecute(){
try{
mDialog = ProgressDialog.show(getActivity(), "", "Loading...!");
}
catch(Exception e)
{
//BadTokenException
e.printStackTrace();
}
}
#Override
protected Void doInBackground(Void... voids) {
Load content...
}
#Override
protected Void onPostExecute(){
if (mDialog != null && mDialog.isShowing()){
mDialog.dismiss();
}
//Put your code after content loaded
afterContentLoad(Object);
}
}
}
Whenever user press back button While fetching xml data from web using AsyncTask my app goes to force close state. How can i solve this. Thanks in advance.
public class InboxActivity extends Activity {
public static ExpandableListView mailList;
List<HashMap<String,String>> list;
MailList asyncTaskMailList;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.inbox_layout);
ConstantValues.footerCurrentActivity=InboxActivity.this;
mailList=(ExpandableListView)findViewById(R.id.expandableListView1);
HomePageActivity.homePageTabHost.getTabWidget().getChildTabViewAt(ConstantValues.CURRENT_POSITION)
.setBackgroundDrawable(getResources().getDrawable(R.drawable.tab_widget_normal));
asyncTaskMailList=new MailList();
asyncTaskMailList.execute();
}
private OnChildClickListener childClickListener=new ExpandableListView.OnChildClickListener() {
public boolean onChildClick(ExpandableListView parent, View v,int groupPosition, int childPosition, long id) {
ConstantValues.STATION_NAME=ConstantValues.inboxStations.get(groupPosition);
ConstantValues.CURRENT_POSITION=1;
startActivity(new Intent(InboxActivity.this, HomePageActivity.class));
return false;
}
};
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK){
this.getParent().onBackPressed();
asyncTaskMailList.cancel(true);
return true;
}
return super.onKeyDown(keyCode, event);
}
#Override
protected void onStop() {
super.onStop();
asyncTaskMailList.cancel(true);
}
#Override
protected void onDestroy() {
asyncTaskMailList.cancel(true);
super.onDestroy();
}
class MailList extends AsyncTask<String, String, String>
{
#Override
protected void onPreExecute() {
super.onPreExecute();
NetworkExceptionPopUp.showProgressBar();
}
#Override
protected String doInBackground(String... params) {
list=new ArrayList<HashMap<String,String>>();
WebServerCall.getInboxMail(InboxActivity.this);
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
mailList.setAdapter(new InboxAdapter(InboxActivity.this));
NetworkExceptionPopUp.dismissProgressBar();
mailList.setOnGroupClickListener(null);
mailList.setOnChildClickListener(childClickListener);
mailList.setClickable(true);
}
}
}
Above code is my updated code. This also sometime shows exception. Here, I had used onStop() and OnDestroy() to cancel AsyncTask while other activity comes top.
#Override
protected void onPreExecute() {
super.onPreExecute();
NetworkExceptionPopUp.showProgressBar();
/** add this line to your progressDialog so that diaolg as well your background operation wont stop in intermediate state. */
// pd.setCancelable(false);
}
So now when you will click back button Dialog will not dismiss.
Hope this help for you.
private MailList task;
#Override
public void onCreate(Bundle savedInstanceState) {
...
task = new MailList().execute();
...
}
#Override
public void onBackPressed() {
if (task != null && task.getStatus() == AsyncTask.Status.RUNNING) {
task.cancel(true);
}
...
}
...