I have a problem related to AsyncTask. I want to change the text inside the onPostExecute method, but it doesn't work. I really don't know what I am doing wrong. Can somebody help me out please?
I don't understand why it work when I declare the AsyncTask as a nested class but it don't work when I declare it as a own class.
Here is my code:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private Button button = null;
private Helper helper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.helper = new Helper(this, getLayoutInflater());
this.button = (Button) findViewById(R.id.button1);
this.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
new MyAsyncTask(helper).execute("");
} catch (Exception e) {
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
}
}
});
}
}
Helper.java
public class Helper {
private Context context;
private LayoutInflater inflater;
public Helper(Context context, LayoutInflater inflater) {
setContext(context);
setInflater(inflater);
}
public Context getContext() {
return context;
}
public void setContext(Context context) {
this.context = context;
}
public LayoutInflater getInflater() {
return inflater;
}
public void setInflater(LayoutInflater inflater) {
this.inflater = inflater;
}
}
MyAsyncTask.java
public class MyAsyncTask extends AsyncTask<String, String, String> {
private Helper helper;
public MyAsyncTask(Helper helper) {
setHelper(helper);
}
public String getJSON(String url, int timeout) {
HttpURLConnection c = null;
try {
URL u = new URL(url);
c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.setRequestProperty("Content-length", "0");
c.setUseCaches(false);
c.setAllowUserInteraction(false);
c.setConnectTimeout(timeout);
c.setReadTimeout(timeout);
c.connect();
int status = c.getResponseCode();
switch (status) {
case 200:
case 201:
BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
br.close();
return sb.toString();
}
} catch (MalformedURLException ex) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
} finally {
if (c != null) {
try {
c.disconnect();
} catch (Exception ex) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
}
}
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(String s) {
TextView t = (TextView) getHelper().getInflater().inflate(R.layout.activity_main, null).findViewById(R.id.textView);
t.setText("" + s); //has no effect on the UI but the text was set????
Toast.makeText(getHelper().getContext(), t.getText(), Toast.LENGTH_LONG).show();
super.onPostExecute(s);
}
#Override
protected String doInBackground(String... params) {
return getJSON("testside.com", 10000);
}
public Helper getHelper() {
return helper;
}
public void setHelper(Helper helper) {
this.helper = helper;
}
}
Thanks :)
Utilize you AsyncTask outside of your main Class using separate files
class MyActivity{
new MyAsyncTask().execute();
}
Your AsyncTask lives as another class Extending AsyncTask
class MyAsyncTask extends AsyncTask{
public MyAsyncTask(Context appContext){
}
}
Be sure to pass in your App's Context. You can only execute each instance of the task once.... but you can create and run a new instance when needed...
Wouldn't fly:
class MyActivity{
MyAsyncTask myTask = new MyAsyncTask();
myTask.execute();
//DO OTHER STUFF
myTask.execute();
}
You would instead do each time needed:
new MyAsyncTask().execute();
Your code looks fine but it doesn't work because it take reference to TextView from new layou which you inflate.
You have two options:
In your helper store TextView which you want to change, you can make it optional if your helper looks something like this:
public class Helper {
private Context context;
private LayoutInflater inflater;
private TextView textView;
...
public void addTextView(TextView textView){
this.texView = textView;
}
public TextView getTextView(){
return textView;
}
}
and then in your postExecute() call TextView t = helper.getTextview().
Pass textView directly to your AsyncTask so it look like
public MyAsyncTask(Helper helper, TextView t) {
setHelper(helper);
this.textView = t;
}
Your AsyncTask is executed on a background thread. To update your UI call,
runOnUiThread(new Runnable() {
#Override
public void run() {
textView.setText("Text");
}
});
on an activity.
Related
I am trying to learn MultiThreading in android although my code works fine when I print the data on Logcat window but my app crashes and gives me a null point exception whenever I try to update a component from the asynctask.
It gives me the following error
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.append(java.lang.CharSequence)' on a null object reference
at com.shivam.asynctasks.MainActivity.logm(MainActivity.java:41)
Line 41
textView.append(message + "\n");
My Code
public class MainActivity extends AppCompatActivity {
Button button ;
TextView textView;
String TAG = "MyTag";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=findViewById(R.id.button);
textView=findViewById(R.id.TextView);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String TAG ="MyTag";
Log.d(TAG,"OnClick Thread Started");
MyTask mytask =new MyTask();
mytask.execute("Red","Black","Yellow","Blue","Orange");
}
});
}
public void logm(String message) {
Log.d(TAG, message);
textView.append(message + "\n");
}
}
class MyTask extends AsyncTask<String,String,String>{
#Override
protected String doInBackground(String... strings) {
String TAG = "MyTag";
for (String value :
strings) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "do in Background : "+value);
publishProgress(value);
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
MainActivity mainActivity =new MainActivity();
for (String color : values) {
mainActivity.logm(color);
}
}
}
You need to reference your activity not create new one. Here you can see.
import android.os.AsyncTask;
public class MainActivity extends AppCompatActivity {
Button button ;
TextView textView;
String TAG = "MyTag";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=findViewById(R.id.button);
textView=findViewById(R.id.TextView);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String TAG ="MyTag";
Log.d(TAG,"OnClick Thread Started");
MyTask mytask =new MyTask(this);
mytask.execute("Red","Black","Yellow","Blue","Orange");
}
});
}
public void logm(String message) {
Log.d(TAG, message);
textView.append(message + "\n");
}
}
class MyTask extends AsyncTask<String,String,String> {
WeakReference<MainActivity> mainActivityRef;
public MyTask(MainActivity activity){
mainActivityRef = new WeakReference<MainActivity>(activity);
}
#Override
protected String doInBackground(String... strings) {
String TAG = "MyTag";
for (String value :
strings) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "do in Background : "+value);
publishProgress(value);
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
MainActivity mainActivity = mainActivityRef.get();
for (String color : values) {
mainActivity.logm(color);
}
}
You are getting the error because the you are creating the instance of the mainactivity class again inside the onProgressUpdate() method whose textView is not initiated. Thats why you are getting the null pointer exception as the textview field is not being initiated.
There is a simple solution to your problem. The onProgressUpdate() method runs on the main UI thread and you have the access to the textview variable inside the onProgressUpdate() method. so simply do the following:
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
MainActivity mainActivity =new MainActivity();
for (String color : values) {
textView.append(color + "\n");
}
}
I am finding the solution of my problem but not satisfied from all of them.
I create an android library which shows a ad view layout witch is and know I want to call this layout in unity but can't find any solution please anyone help me how can I call my layout in unity?
public class RedeemLayout extends LinearLayout implements View.OnClickListener,HttpCallBacks {
public Dialog dialogBox;
public ImageButton close;
public ImageView advert;
public TextView location_text;
TextView tv_massagetext;
EditText et_redeemdetial;
Button btn_redem;
ImageButton btn_closead;
DeviceInfo device = new DeviceInfo();
String adClickUrl;
HttpNetworkCalls httpNetworkCalls;
Context context;
Activity activity;
ImageView bmImage;
FrameLayout redeemLayout;
AdInfo ad;
private AdInfo adInfo;
private UserInfo user;
public RedeemLayout(Context context) {
super(context);
initialize(context);
this.context = context;
}
public RedeemLayout(Activity activity, Context context) {
super(context);
initialize(context);
this.context = context;
this.activity = activity;
}
public RedeemLayout(Context context, AttributeSet attr) {
super(context, attr);
initialize(context);
this.context = context;
}
private void initialize(Context context) {
inflate(context, R.layout.ad_lyout, this);
tv_massagetext = (TextView) findViewById(R.id.massagetext);
et_redeemdetial = (EditText) findViewById(R.id.redeemdetail);
btn_redem = (Button) findViewById(R.id.btn_redeem);
btn_closead = (ImageButton) findViewById(R.id.btn_CloseFullScreenAd);
bmImage = (ImageView) findViewById(R.id.adimage);
redeemLayout = (FrameLayout) findViewById(R.id.redeemLayout);
httpNetworkCalls = new HttpNetworkCalls(this);
btn_redem.setOnClickListener(this);
btn_closead.setOnClickListener(this);
DownloadAdAccordingToLocation();
}
public void onClick(View view) {
int i = view.getId();
if (i == R.id.btn_redeem) {
Toast.makeText(getContext(), "Thanks for Redeem You will get Massage soon...", Toast.LENGTH_LONG).show();
Map<String, String> data = new HashMap<>();
data.put("ad_id",ad.getAdId());
data.put("app_id","1");
data.put("location","lahore");
data.put("session","1");
try {
httpNetworkCalls.post(data, API.UPDATE_IMPRESSIONS);
// call AsynTask to perform network operation on separate thread
} catch (Exception e) {
e.printStackTrace();
}
// call AsynTask to perform network operation on separate thread
}
if (i == R.id.btn_CloseFullScreenAd) {
redeemLayout.removeAllViews();
redeemLayout.setVisibility(View.GONE);
Map<String, String> data = new HashMap<>();
data.put("ad_id",ad.getAdId());
data.put("app_id","1");
data.put("location","lahore");
data.put("session","1");
Toast.makeText(getContext(), "Thanks for Redeem You will get Massage soon...", Toast.LENGTH_LONG).show();
try {
httpNetworkCalls.post(data, API.UPDATE_IMPRESSIONS);
// call AsynTask to perform network operation on separate thread
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void DownloadAdAccordingToLocation() {
try {
httpNetworkCalls.get(API.RANDOM_ADVERTISEMENT);
} catch (IOException e) {
e.printStackTrace();
}
}
public void adButtonClicked(View v) {
// FullScreenAdDialog db = new FullScreenAdDialog(this, ad, updateAdClick);
// db.show();
// Intent x = new Intent(xcontext, AdActivity.class);
// x.putExtra("image_link", ad.getImage_link());
// x.putExtra("url", ad.getUrl());
// x.putExtra("adid", ad.getAdId());
// x.putExtra("adclickurl", updateAdClick);
// startActivity(x);
}
#Override
public void HttpResponse(final int apiCode, final JSONObject response, final boolean isSuccess) {
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
try {
if (apiCode == API.RANDOM_ADVERTISEMENT) {
if (response.has("networkError")) {
Log.e("Error", response.getString("networkError"));
} else {
ad = AdInfo.fromJson(response);
if (ad.isSuccess()) {
Picasso.Builder builder = new Picasso.Builder(context);
builder.listener(new Picasso.Listener() {
#Override
public void onImageLoadFailed(Picasso picasso, Uri uri, Exception exception) {
redeemLayout.removeAllViews();
redeemLayout.setVisibility(View.GONE);
}
});
Picasso pic = builder.build();
pic.load(ad.getImage_url()).into(bmImage);
// Picasso.with(context)
// .load(ad.getImage_url())
// .error(R.drawable.imagecross)
// .into(bmImage);
} else {
Log.e("Error", response.getString("parseError"));
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
and call my library in android app like this.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RelativeLayout layout= (RelativeLayout)findViewById(R.id.test);
RedeemLayout redeemLayout= new RedeemLayout(this, this);
redeemLayout.setGravity(Gravity.CENTER);
layout.addView(redeemLayout);
}
}
It's more unity3d question. You cannot call your layout directly, you can only send message to android code. Read Unity3d script documentation (or google for code) of AndroidJavaClass and AndroidJavaObject.
From Android perspective I think that you should implement some kind of static method that you can call from unity and it should broadcast or send event in event bus that will be handled by your advertisement engine.
Unity part of code should be similar to this:
AndroidJavaClass javaClass = new AndroidJavaClass("com.mypackage.MyClassWithMyStaticMethod");
javaClass.getStatic<AndroidJavaObject>("MyStaticMethod", 42);
Android MyClassWithMyStaticMethod class should implement:
public static void MyStaticMethid(int param) {...}
Check this doc: AndroidJavaClass
I'm trying to return value from my asynctask in DoInBackground, but calling get() method freezes my UI. How can I re-write my code to a callback method? :
public class GetUrlDataTask extends AsyncTask<String, Integer, String> {
String response;
HttpUtils util;
#Override
protected String doInBackground(String... params) {
try {
util = new HttpUtils(params[0]);
response = util.getContent();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return response;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}
In my activity I get result as response = new GetUrlDataTask().execute("site").get;
You shouldn't use .get() if the Async task is going to take any decent amount of time (which it usually is).
Instead, you can either use a message/handler/service/etc, or you can simply use the onPostExecute(Result) method.
EDIT: New Code. Based on your description, it seems like you need to use an interface.
If you need to have Asynctask in another class, then an interface is probably your best option.
TestTask.java (your separate Asynctask):
import android.os.AsyncTask;
// Remember to change object type <> to what you need
public class TestTask extends AsyncTask<Object,Object,Object> {
public interface OnTaskCompleted{
void onTaskCompleted();
}
private OnTaskCompleted listener;
public TestTask(OnTaskCompleted listener){
this.listener = listener;
}
protected void onPostExecute(Object o){
// Call the interface method
if (listener != null)
listener.onTaskCompleted();
}
#Override
protected Object doInBackground(Object... params) {
// The sleep() is just to simulate activity and delay
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}
MainActivity.java (or any other activity):
public class MainActivity extends Activity {
private boolean status = false;
private OnTaskCompleted listener = new OnTaskCompleted() {
public void onTaskCompleted() {
status = true;
Toast.makeText(MainActivity.this, "Status: " + status, Toast.LENGTH_SHORT).show();
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toast.makeText(MainActivity.this, "Status: " + status, Toast.LENGTH_SHORT).show();
new TestTask(listener).execute("Testing");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
I'm not a big fan of having AsycTask tasks in separate classes, especially if you need to use the response. It makes interacting with the response and local variables overly difficult considering how easy it is when implemented as an inner class.
I'm guessing you put it in its own class so you can reuse it. I would consider keeping the AsycTask as an inner class and calling outside reusable objects/methods in doInBackground(). This will keep the code DRY and allow your activity to do what it needs with the response.
public class MyActivity extends Activity {
TextView textview;
//...
private class GetUrlTask extends AsyncTask<String, Integer, String> {
protected String doInBackground(String... params) {
return new GetHttpResponse().get(params[0]);
}
protected void onPostExecute(String response) {
//Do UI updates...
textview.setText(response);
}
}
}
public class GetHttpResponse {
public String get(String url) {
try {
util = new HttpUtils(url);
response = util.getContent();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return response;
}
}
You could do something like this:
public class MyActivity extends Activity
{
public void someMethod()
{
// Here you could put up a ProgressDialog
GetUrlDataTask myTask = new GetUrlDataTask();
myTask.execute();
}
public class GetUrlDataTask extends AsyncTask<String, Integer, String>
{
#Override
protected String doInBackground(String... params)
{
String response = null;
HttpUtils util;
try
{
util = new HttpUtils(params[0]);
response = util.getContent();
}
catch (Exception e)
{
e.printStackTrace();
response = e.getMessage();
}
return response;
}
#Override
protected void onPostExecute(String result)
{
// Here you can dismiss the ProgressDialog and display the result
}
}
}
I have an android app that I am having trouble with.
Basically the ProgressDialog is not showing at all. I believe this to be a threading issue of some sort but I don't know how to fix it.
I am using ActionBarSherlock with some Fragments. I am also using the new Android DrawerLayout where I have my options on the drawer, which replace a fragment when clicked.
On first load of my app, I want to check the database to see if the inital data has been downloaded. If not, then I go off and begin an AsyncTask to download the data. This SHOULD have a ProgressDialog display during this, but it doesnt.
Can someone see where I am going wrong? Thanks.
MainScreen - The default landing page/fragment when the app opens
public class MainScreen extends SherlockFragment {
public static final String TAG = "MainScreen";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_main, container, false);
setHasOptionsMenu(false);
ImageView imgLogo = (ImageView) rootView.findViewById(R.id.imgMainScreen);
imgLogo.setOnClickListener(new ButtonHandler(getActivity()));
checkDatabase();
return rootView;
}
private void checkDatabase() {
//Ensure there is data in the database
DBHelper db = new DBHelper(this.getSherlockActivity());
db.checkDatabase();
}
...
}
DBHelper.checkDatabase() - The method that initiates the download
public void checkDatabase() {
if (isEmpty()) {
//Connect to net and download data
NetworkManager nm = new NetworkManager(activity);
if (!nm.downloadData()) {
Toast.makeText(activity, R.string.internetCheck, Toast.LENGTH_SHORT).show();
}
}
}
and finally
NetworkManager.downloadData() - The method that kicks off the AsyncTask:
public boolean downloadData() {
try {
return new HttpConnection(activity).execute().get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return false;
}
public class HttpConnection extends AsyncTask<Void, Void, Boolean> {
private ProgressDialog progressDialog;
private Activity m_activity;
protected HttpConnection(Activity activity) {
m_activity = activity;
}
#Override
protected void onPreExecute() {
progressDialog = new ProgressDialog(m_activity);
progressDialog.setMessage("Wait ...");
progressDialog.setCancelable(false);
progressDialog.setMax(100);
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.show();
super.onPreExecute();
}
#Override
protected Boolean doInBackground(Void... params) {
String[] types = new String[]{"type1", "type2", "type3", "type4", };
StringBuilder sb = new StringBuilder();
for(String type : types) {
sb = new StringBuilder();
if(DBHelper.TYPE4_TABLE.equals(type)) {
InputStream is = activity.getResources().openRawResource(R.raw.dbdata);
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
try {
sb.append(reader.readLine());
} catch (IOException e) {
Toast.makeText(activity.getApplicationContext(), "Error retriveving data", Toast.LENGTH_SHORT).show();
Log.e(Constants.TAG, "Error reading data");
e.printStackTrace();
}
} else {
sb = fetchURLData(Constants.ALL_URL+type);
}
cleanDataAndStore(sb, type);
}
return true;
}
#Override
protected void onPostExecute(Boolean result){
progressDialog.hide();
}
}
Using the above code, all I get is a white screen as the app tries to load, and sometimes an ANR. When the download is done, the fragment loads. So it works fine except for the missing ProgressDialog.
PS, Notice I'm setting the activity in each constructor.
Thanks.
Remove .get() from return new HttpConnection(activity).execute().get(); You are basically locking your UI thread. Once removed it should work as AsyncTasks are expected to work.
The purpose is to be Asynchronous so boolean downloadData() should have a return type of void. If you need to do something with the data then you should implement an interface "listener" and pass it to the AsyncTask.
Example Listener:
class TaskConnect extends AsyncTask<Void, Void, ConnectionResponse> {
private final AsyncTaskListener mListener;
/**
*
*/
public TaskConnect(AsyncTaskListener listener) {
...
mListener = listener;
}
#Override
protected void onPreExecute() {
if (mListener != null) {
mListener.onPreExecute(mId);
}
}
#Override
protected ConnectionResponse doInBackground(Void... cData) {
...
return responseData;
}
#Override
protected void onPostExecute(ConnectionResponse response) {
if (mListener != null) {
mListener.onComplete(response);
} else {
LOG.w("No AsyncTaskListener!", new Throwable());
}
}
}
public interface AsyncTaskListener {
public abstract void onPreExecute(int id);
public abstract void onComplete(ConnectionResponse response);
}
My issue was not the common issue of others where they were calling get() method after execute() method. My issue was the Context I was passing to my AsyncTask method. I have a settingsActivity and I have a ReadMeActivity that calls the asynctask task. Instead of using the context in which is was being called (ReadMeActivity.this) I used the settingsActivity which prevented it from being seen. Once I switched it and passed it the context in which the activity was being called it worked.
Hope it helps someone else.
I'm doing the refactoring of an application that uses AsyncTask to make HTTP calls to a web service.
Now use a simple Activity, at the moment when I needs to invoke the service using a AsyncTask in this way:
private class MyAsyncTask extends AsyncTask {<String, Void, Boolean>
private ProgressDialog progressDialog;
private xmlHandler handler;
# Override
protected void OnPreExecute () {
progressDialog = new ProgressDialog (home.This);
progressDialog
. SetMessage (getString (R.string.home_loadinfo_attendere));
progressDialog.setCancelable (false);
progressDialog.show ();
}
# Override
protected Boolean doInBackground (String... params) {
try {
xmlHandler handler = new XmlHandler();
return Service
. GetInstance ()
. CallService (
ServiceType.GETINFO,
Home.This, handler, null);
} Catch (Exception e) {
e.printStackTrace ();
return false;
}
}
# Override
protected void OnPostExecute (Boolean success) {
progressDialog.dismiss ();
String message = null;
if (success | | (handler == null))
message = getString (R.string.server_result_msg500);
else {
switch (handler.getStatusCode ()) {
case 200:
doStuffWithHandler(handler);
return;
case 500:
message = getString (R.string.server_result_msg500);
break;
case 520:
message = getString (R.string.server_result_msg520);
break;
default:
message = getString (R.string.server_result_msg500);
break;
}
}
if (message! = null) {
AlertDialog.Builder builder = new AlertDialog.Builder (home.This);
builder.setTitle (R.string.home_loadinfo_error_title)
. SetMessage (message)
. SetCancelable (true)
. SetNegativeButton (R.string.close_title,
new DialogInterface.OnClickListener () {
# Override
public void onClick (DialogInterface dialog,
int id) {
dialog.cancel ();
}
});
AlertDialog alert = builder.create ();
Alert.show ();
}
}
}
doStuffWithHandler(handler){
// populate interface with data from service
}
I want to do the same but using Android compatibility libraries and FragmentActivity. I read a little about loader but I did not understand how I could use them in this same way, Could you please tell me if this is the right way (FragmentActivity, Fragment and Loader) and how to implement it also addresses giving me examples?
You could create a Loader, something like this:
public abstract class MyLoader extends AsyncTaskLoader<String> {
public MyLoader(Context context) {
super(context);
}
private String result;
protected String error;
#Override
public final String loadInBackground() {
try {
error = null;
// Load your data from the server using HTTP
...
result = ...
...
return result;
}
catch (Exception e) {
Logger.e("ResourceLoader", "Loading resource failed.", e);
error = e.getMessage();
}
return null;
}
#Override
protected void onStartLoading() {
if (!TextUtils.isEmpty(error)) {
deliverResult(result);
}
if (takeContentChanged()) {
forceLoad();
}
}
#Override
public void deliverResult(String data) {
if (isReset()) {
return;
}
result = data;
if (isStarted()) {
try {
super.deliverResult(data);
}
catch(Exception e) {
Log.e("ResourceLoader", "Caught exception while delivering result.", e);
}
}
}
public String getError() {
return error;
}
}
In your Fragment, you can initialize this loader:
public class MyLoaderFragment extends Fragment implements LoaderCallbacks<String> {
....
....
String message;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
....
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getLoaderManager().initLoader(0, getArguments(), this);
}
#Override
public Loader<String> onCreateLoader(int id, Bundle args) {
return new MyLoader(getActivity());
}
#Override
public void onLoadFinished(Loader<String> loader, String result) {
// Here you have the result in 'result'.
message = result;
...
}
....
}
And instead of just returning a simple 'String' result, you can return any object you like. Just adjust the MyLoader and LoaderCallbacks implementation accordingly.
You can use Asynctask in Fragment exactly as you did in your Activity, few things change, like:
progressDialog = new ProgressDialog (home.This);
change to:
progressDialog = new ProgressDialog (getApplication());
return Service
. GetInstance ()
. CallService (
ServiceType.GETINFO,
Home.This, handler, null);
change to:
return Service
. GetInstance ()
. CallService (
ServiceType.GETINFO,
getApplication(), handler, null);
Anything special to implements Asynctask in Fragment.
I think you need to read more about Fragment itself.