Handling AsyncTask warning class should be static or leaks might occur - java

I have created as asynctask to upload data to a server as below. But it shows this warning.
This AsyncTask class should be static or leaks might occurs......
I have read and tried the weak reference style but i cant be able to integrate in this code.
How can I get rid of this warning in the code below?.
public void ImageUploadToServerFunction(){
final String imageName1 = GetImageNameEditText1.trim();
final String userName = GetUserName.trim();
final String imageView1 = getStringImage1(bitmap1);
class AsyncTaskUploadClass extends AsyncTask<Void,Void,String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = ProgressDialog.show(UploadActivity.this,"Your Data is Uploading....",false,false);
}
#Override
protected void onPostExecute(String string1) {
super.onPostExecute(string1);
progressDialog.dismiss();
}
#Override
protected String doInBackground(Void... params) {
ImageProcessClass imageProcessClass = new ImageProcessClass();
HashMap<String,String> HashMapParams = new HashMap<>();
HashMapParams.put(ImageName1, imageName1);
HashMapParams.put(UserName, userName);
HashMapParams.put(ImagePath1, imageView1);
return imageProcessClass.ImageHttpRequest(ServerUploadPath, HashMapParams);
}
}
AsyncTaskUploadClass AsyncTaskUploadClassOBJ = new AsyncTaskUploadClass();
AsyncTaskUploadClassOBJ.execute();
}

If you're executing this in the context of a function, you need to make your AsyncTask anonymous. Something like:
public void ImageUploadToServerFunction(){
final String imageName1 = GetImageNameEditText1.trim();
final String userName = GetUserName.trim();
final String imageView1 = getStringImage1(bitmap1);
new AsyncTask<Void,Void,String>() {
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = ProgressDialog.show(UploadActivity.this,"Your Data is Uploading....",false,false);
}
#Override
protected void onPostExecute(String string1) {
super.onPostExecute(string1);
progressDialog.dismiss();
}
#Override
protected String doInBackground(Void... params) {
ImageProcessClass imageProcessClass = new ImageProcessClass();
HashMap<String,String> HashMapParams = new HashMap<>();
HashMapParams.put(ImageName1, imageName1);
HashMapParams.put(UserName, userName);
HashMapParams.put(ImagePath1, imageView1);
return imageProcessClass.ImageHttpRequest(ServerUploadPath,HashMapParams);
}
}.execute();
}
But I highly recommend not using AsyncTask in Android anymore. It's a very dirty way to do asynchronous operations and it rightfully should be deprecated. A better way to solve this would be with RxJava.

Related

Getting an Arraylist from an inner AsyncTask class

I've parsed some XML Data in Asynctask and printed it in the log, but whenever I try to copy the ArrayList of data into my Activity, it always remains null.
Here's the code,
public class MainActivity extends AppCompatActivity {
static ArrayList<NewsItems>myData=new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ReadRss readRss = new ReadRss(this);
readRss.execute();
Log.d("TAG", String.valueOf(myData.size()));//This stays empty
}
public static void getData(ArrayList<NewsItems>items){
for (int i=0; i<items.size(); i++){
myData.add(items.get(i));
}
}
class ReadRss extends AsyncTask<Void, Void, Void>{
ArrayList<NewsItems>feedItems = new ArrayList<>();
Context context;
String address = "http://www.thedailystar.net/frontpage/rss.xml";
ProgressDialog progressDialog;
URL url;
public ReadRss(Context context) {
this.context = context;
progressDialog = new ProgressDialog(context);
progressDialog.setMessage("Loading...");
}
#Override
protected void onPreExecute() {
if(progressDialog!=null){
if (!progressDialog.isShowing()){
progressDialog.show();
}
}
super.onPreExecute();
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if(progressDialog!=null){
if (progressDialog.isShowing()){
progressDialog.hide();
}
}
MainActivity.getData(feedItems);
}
#Override
protected Void doInBackground(Void... params) {
ProcessXml(Getdata());
return null;
}
private void ProcessXml(Document data) {
if (data != null) {
Element root = data.getDocumentElement();
Node channel = root.getChildNodes().item(1);
NodeList items = channel.getChildNodes();
for (int i = 0; i < items.getLength(); i++) {
Node currentchild = items.item(i);
if (currentchild.getNodeName().equalsIgnoreCase("item")) {
NewsItems item=new NewsItems();
NodeList itemchilds = currentchild.getChildNodes();
for (int j = 0; j < itemchilds.getLength(); j++) {
Node current = itemchilds.item(j);
if (current.getNodeName().equalsIgnoreCase("title")){
item.setTitle(current.getTextContent());
}else if (current.getNodeName().equalsIgnoreCase("description")){
item.setDescription(current.getTextContent());
}else if (current.getNodeName().equalsIgnoreCase("media:thumbnail")){
item.setMedia(current.getAttributes().getNamedItem("url").getTextContent());
}else if (current.getNodeName().equalsIgnoreCase("link")){
item.setUrl(current.getTextContent());
}
}
feedItems.add(item);
Log.d("itemTitle", item.getTitle());
Log.d("itemDescription",item.getDescription());
Log.d("itemMediaLink",item.getMedia());
Log.d("itemLink",item.getUrl());
}
}
}
}
public Document Getdata() {
try {
url = new URL(address);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
InputStream inputStream = connection.getInputStream();
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document xmlDoc = builder.parse(inputStream);
return xmlDoc;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
}
I tried calling a static method of the Activity in the onPostExecute method, it doesn't work.
1) You should declare the ArrayList variable as a member of mainActivity and then pass its reference into the Asynctask.
2) You can verify that the data is present in the list, only after you are sure the Asynctask has completed processing. (You can do that within the onPostExecute of the AsyncTask).
public class MainActivity extends AppCompatActivity {
ArrayList<NewsItems>myData=new ArrayList<>(); //No need for static
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ReadRss readRss = new ReadRss(this,myData); //Pass the list variable reference into the asynctask instance
readRss.execute();
Log.d("TAG", String.valueOf(myData.size()));//This will be empty due to concurrent call to asynctask, which executes parallel to main thread.
}
public void getData(ArrayList<NewsItems>items){//Static qualifier unneccessary here
for (int i=0; i<items.size(); i++){
myData.add(items.get(i));
}
}
class ReadRss extends AsyncTask<Void, Void, Void>{
ArrayList<NewsItems>feedItems = new ArrayList<>();
Context context;
String address = "http://www.thedailystar.net/frontpage/rss.xml";
ProgressDialog progressDialog;
URL url;
public ReadRss(Context context,ArrayList<NewsItems> feedItems) {
this.context = context;
this.feedItems = feedItems; //Assign the reference of the list here so that modifications done within the Asynctask are reflected in the MainActivity
progressDialog = new ProgressDialog(context);
progressDialog.setMessage("Loading...");
}
#Override
protected void onPreExecute() {
if(progressDialog!=null){
if (!progressDialog.isShowing()){
progressDialog.show();
}
}
super.onPreExecute();
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if(progressDialog!=null){
if (progressDialog.isShowing()){
progressDialog.hide();
}
}
//Do whatever you need with the arraylist data here
getData(feedItems);
}
#Override
protected Void doInBackground(Void... params) {
ProcessXml(Getdata());
return null;
}
Avoid static variables as much as possible. Unnecessary static fields land you into problems hard to understand.
If you are populating it in an AdapterView like ListView, remember to call adapter.notifyDataSetChanged() when you have the data set ready with you.
You can actually pass the result of your doInBackground() to onPostExecute() to continue doing your work on the calling thread, which is the main thread in your case.
new AsyncTask<Void, Void, ArrayList<NewsItems>>() {
#Override
protected ArrayList<NewsItems> doInBackground(Void... params) {
ArrayList<NewsItems> response = whatEverMethodGetsMeNetworkCallResponse();
return response;
}
#Override
protected void onPostExecute(ArrayList<NewsItems> response) {
super.onPostExecute(response);
// Do whatever you want to do with the network response
}
}.execute();
Or you can even set up listeners and do it in a more sophisticated way like:
onCreate() {
...
getNewsItems(new NewsItemsListener() {
void onFetched(ArrayList<NewsItems> items) {
// Do whatever you want to do with your news items
}
});
}
public void getNewsItems(final NewsItemsListener listener)
new AsyncTask<Void, Void, ArrayList<NewsItems>>() {
#Override
protected ArrayList<NewsItems> doInBackground(Void... params) {
ArrayList<NewsItems> response = whatEverMethodGetsMeNetworkCallResponse();
return response;
}
#Override
protected void onPostExecute(ArrayList<NewsItems> response) {
super.onPostExecute(response);
listener.onFetched(response);
}
}.execute();
}
public interface NewsItemsListener {
void onFetched(ArrayList<NewsItems> items);
}

AsyncTask onPostExecute listener [duplicate]

This question already has answers here:
how to return result from asyn call
(2 answers)
Closed 7 years ago.
Activity.java
//Activity stuff
MyClass mc = new MyClass();
mc.getText();
public void dosomething() {
textview.setText(mc.getText());
}
MyClass.java
class MyClass {
String text;
public void setText() {
class GetTextFromWEB extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String url = urls[0];
String output;
//Getting text from web
return output;
}
#Override
protected void onPostExecute(String _text) {
text = _text;
}
}
String url = "google.com";
//Doing with url something
new GetText().execute(url);
}
public String getText() {return text;}
}
Promblem is - in activity setText do faster, then AsyncTask do it's job.
So when setText run, it's run like setText(null)
I need to check in activity, is asynk ended, so i have my text to set.
I hope i explained it
And i don't even need exactly AsyncTask, i need jsoup working, so if there is solution with another thread-class, with which jsoup will work, i can use it
Edit
class GetLyrics extends AsyncTask<String, Void, String> { //Class for getting lyrics
private Context con;
public GetLyrics(Context con) {
this.con = con;
}
#Override
protected String doInBackground(String... urls) {
//do something
}
#Override
protected void onPostExecute(String _lyrics) {
lyrics = _lyrics;
con.runOnUiThread(new Runnable() {
#Override
public void run() {
((TextView) findViewById(R.id.lyricsOutput)).setText(lyrics);
}
});
}
}
Call the method setting your text in the postExecute inside your AsyncTask or set the text directly on your postExecute method.
And wrap the line with setText() inside runOnUIThread (otherwise you will get an exception saying that the view can be accessed only by the thread that created it, since you are setting the text from async task).
Setting the text would be something like this
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
((TextView) findViewById(R.id.txtFieldName)).setText("your text");
}
});
That way you can quit worrying about checking if the async task is finished. But avoid doing complex ui operations like this. Since this is just setting the text on TextView, it should be allright.
1: Make my first project from my previous post and add some new lines in it to get data from http: api's.
public class Example extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example);
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("parameter1", "xyz"));
params.add(new BasicNameValuePair("parameter2", "abc"));
params.add(new BasicNameValuePair("parameter3", "opqr"));
ServerConnection task = new ServerConnection(this, new ResultListener() {
#Override
public void result(String response) {
Toast.make(this, response, Toast.LENGTH_LONG).show();
}
#Override
public void loader(boolean visble) {
}
#Override
public void connectionLost(String error) {
Toast.make(this, error, Toast.LENGTH_LONG).show();
}
});
}
public class ServerConnection extends AsyncTask<String, String, String> implements Constant {
ResultListener listener;
private String Method = "GET";
private List<NameValuePair> params = new ArrayList<NameValuePair>();
private Context context;
private ConnectionDetector cd;
// public static Drawable drawable;
public ServerConnection(Context context, ResultListener r) {
this.context = context;
this.listener = r;
cd = new ConnectionDetector(context);
this.execute();
}
public boolean isConnection() {
return cd.isConnectingToInternet();
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... arg0) {
if (!isConnection()) {
cancel(true);
return "Sorry!connection lost,try again or later";
}
ApiResponse air = new ApiResponse();
System.out.println("working hre" + "hi");
String json;
try {
json = air.makeHttpRequest(URL, getMethod(), getParams());
} catch (Exception e) {
json = e.getMessage();
cancel(true);
return json;
}
return json;
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
#Override
protected void onCancelled(String result) {
listener.connectionLost(result);
rl.connectionLost("Sorry!connection lost,try again or later");
super.onCancelled(result);
}
#Override
protected void onPostExecute(String result) {
System.out.println("onpost" + result);
listener.result(result);
listener.loader(true);
super.onPostExecute(result);
}
public String getMethod() {
return Method;
}
public void setMethod(String method) {
Method = method;
}
public List<NameValuePair> getParams() {
return params;
}
public void setParams(List<NameValuePair> params) {
this.params = params;
}
}
Example

Calling notifyOnDataSetChanged in AsyncTask (not within the class)

*************PROBLEM FIXED, CHECK BELOW FOR A SOLUTION*************
I have been struggling with that nearly half a day. Cannot get it work properly.
I have AsyncTask with private method, so I can pass boolean and String values in CustomLvAdapter
private void changeJobStatus(final boolean isAppliedforAJob, final String jobID){
class ChangeJobStatus extends AsyncTask<Void,Void,String> {
//private Delegates del = null;
ProgressDialog loading;
#Override
protected void onPreExecute() {
super.onPreExecute();
if(isAppliedforAJob) {
loading = ProgressDialog.show(context, "","Canceling application", false);
}
else {
loading = ProgressDialog.show(context, "","Applying for position", false);
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
//del.asyncCompleteOnCustomJob(true);
loading.dismiss();
}
#Override
protected String doInBackground(Void... v) {
String res;
HashMap<String,String> params = new HashMap<>();
params.put(Config.KEY_USER_ID, studentID);
params.put(Config.KEY_JOB_ID, jobID);
RequestHandler rh = new RequestHandler();
if(isAppliedforAJob)
res = rh.sendPostRequest(Config.URL_CANCEL_APPLICATION, params);
else
res = rh.sendPostRequest(Config.URL_APPLY_FOR_A_JOB, params);
Log.d("Stringas", "CustomListViewBackground " + res);
return res;
}
}
ChangeJobStatus cjs = new ChangeJobStatus();
cjs.execute();
}
and in onPostExcecute() I want to call notifyOnDataSetChanged() to my another activity lvAdapters.
As far as I read I have to implement delegate interface, but I didnt succeed doing that. I fail at initializing delegate in my main class, because changeJobStatus method is private and it is called in customLvAdapter class.
If I make a constructor in ChangeJobStatus class
public ChangeJobStatus(Delegates delegate)
{
this.del = delegate;
}
I have to pass something in the parameters, when excecuting it. If I pass new Delegate, my delegate implementation, which is in my another activity is not triggered.
ChangeJobStatus cjs = new ChangeJobStatus(new Delegates() {
#Override
public void asyncCompleteOnCustomJob(boolean success) {
//whatever
}
});
cjs.execute();
I hope you can help me figure out right implementation for that,
Cheers
***********SOLUTION***********
Sadly, I couldn't implement what fellow user gave to me, but I am very glad that I heard from one of you I can use broadcast receiver. And it worked.
This is what I did
Create a Broadcast Receiver in your main class
private final BroadcastReceiver broadcastJobList = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//what will happen, when event triggers
}
};
Register custom intent and register it to Broadcast receiver in your main class onCreate method or wherever you feel comfortable :)
IntentFilter filter = new IntentFilter();
filter.addAction("jobListChanged");
registerReceiver(broadcastJobList, filter);
All we left to do is send intent which will trigger Broadcast receiver. Following code in my scenario went to onPostExcecute method in custom adapter (context was initialized for Context at the beggining of custom adapter)
Intent intent = new Intent();
intent.setAction("jobListChanged");
context.sendBroadcast(intent);
Hope I will help anyone that has this problem. Cheers!
// your asynctask class
public class ChangeJobStatus extends AsyncTask<String, Void, String> {
private ProgressDialog loading;
private OnResponseListener responseListener;
private boolean isAppliedforAJob;
private Context con;
public ChangeJobStatus(Context con,boolean state) {
super();
// TODO Auto-generated constructor stub
this.con=con;
isAppliedforAJob = state;
}
public void setOnResponseListener(OnResponseListener onLoadMoreListener) {
this.responseListener = onLoadMoreListener;
}
public interface OnResponseListener {
public void onResponse(String responsecode);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
if (isAppliedforAJob) {
loading = ProgressDialog.show(con, "", "Canceling application", false);
} else {
loading = ProgressDialog.show(con, "", "Applying for position", false);
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
// del.asyncCompleteOnCustomJob(true);
loading.dismiss();
responseListener.onResponse(s);
}
#Override
protected String doInBackground(String... param) {
String res="";
HashMap<String, String> params = new HashMap<>();
params.put(Config.KEY_JOB_ID, param[0]);// job id
params.put(Config.KEY_USER_ID, param[1]);// student id
RequestHandler rh = new RequestHandler();
if (isAppliedforAJob)
res = rh.sendPostRequest(Config.URL_CANCEL_APPLICATION, params);
else
res = rh.sendPostRequest(Config.URL_APPLY_FOR_A_JOB, params);
return res;
}
}
in your activity class
public class MainActivity extends Activity implements OnResponseListener {
String jobId="1",studId="1";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ChangeJobStatus cbs=new ChangeJobStatus(this, true);
cbs.setOnResponseListener(this);
cbs.execute(jobId,studId);
}
#Override
public void onResponse(String responsecode) {
// TODO Auto-generated method stub
//here u can do ur stuff with the string
}
}

doInBackground of asyncTask not getting called?

In my app, when I call new RetrieveFirstThreeArtUrl().execute() doInBackground isn't getting called.. does anyone know why? This code was working a few days ago, so I have no idea what's going on..
public class RetrieveFirstThreeArtUrl extends AsyncTask<String, Void, Void> {
static final String APIURL = "http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key=2ead17554acf667f27cf7dfd4c368f15&artist=%s&album=%s";
static final String APIURL_ARTIST = "http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&api_key=2ead17554acf667f27cf7dfd4c368f15&artist=%s";
#Override
public void onPreExecute() {
super.onPreExecute();
Log.v("", "Pre");
}
#Override
public Void doInBackground(String... args) {
Log.v("", "Background");
return null;
}
#Override
public void onPostExecute(Void args) {
list = (ListView) rootView.findViewById(R.id.list);
adapter = new LiveAdapter(LiveStreamFragment.this.getActivity(), oslist, LiveStreamFragment.this, list);
list.setAdapter(adapter);
}
}
Replace your code with this
before calling RetrieveFirstThreeArtUrl method, write these two lines
static final String APIURL = "http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key=2ead17554acf667f27cf7dfd4c368f15&artist=%s&album=%s";
static final String APIURL_ARTIST = "http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&api_key=2ead17554acf667f27cf7dfd4c368f15&artist=%s";
And than call method RetrieveFirstThreeArtUrl, one more thing, use protected instead of public
public class RetrieveFirstThreeArtUrl extends AsyncTask<String, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
Log.v("", "Pre");
}
#Override
protected void onPostExecute(Void result) {
list = (ListView) rootView.findViewById(R.id.list);
adapter = new LiveAdapter(LiveStreamFragment.this.getActivity(), oslist, LiveStreamFragment.this, list);
list.setAdapter(adapter);
}
#Override
protected Void doInBackground(String... params) {
Log.v("", "Background");
return null;
}
}

Async task not working

Hey i have a problem with my android application.I'm trying to download text from given url to Editable box but when i'm running application and hit the button it suddenly stops working.I am using asynctask to download, also eclipse tells me that class DownloadTask is not used locally
public void sendMessage(View view) throws IOException {
new DownloadTask().execute();
}
private class DownloadTask extends AsyncTask{
protected Object doInBackground(Object... params) {
// TODO Auto-generated method stub
try {
EditText tf = (EditText) findViewById(R.id.editText1);
String kupa = tf.getText().toString();
Document doc;
doc = Jsoup.connect(kupa).get();
String title = doc.text();
TextView tv = (TextView) findViewById(R.id.textView1);
tv.setText(title);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String result) {
TextView tv = (TextView) findViewById(R.id.textView1);
tv.setText(result);
}
}
Also i added two lines of code to my onCreate method
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
If this helps min api is 10,target is 16
cheers guys
you can't run UI code in doInBackground.
you try run bellow code on doInBackground, delete that or move it to onPostExecute
tv.setText(title);
and you don't need following line:
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
if you need value in AyncTask you can pass data, if you need tf.getText().toString() you can change your code with following code:
new DownloadTask().execute(tf.getText().toString());
and change AsyncTask class with:
public static class DownloadTask extends AsyncTask<String, Void, Void>
{
#Override
protected Void doInBackground(String... params)
// use params array, in this example you can get tf.getText().toString() with params[0]
String kupa = params[0] // if you pass more data you can increase index
}
for more info see documentation of AsyncTask
:( Now, we can talk about Thread.
hmm...
You are using AsyncTask to download text from url.
It mean you are using another thread to do.
And another thread could not change UI. You must change UI in main thread. But if you want to change UI in other thread you can use runOnUIThread method.
I can give you a solution for your issue.
A child of AsyncTask
public class AsyncLoadData extends AsyncTask<String, Void, String> {
private Context mContext;
private ILoadDataListener mListener;
public AsyncLoadData(Context context, ILoadDataListener listener) {
this.mContext = context;
this.mListener = listener;
}
#Override
protected String doInBackground(String... params) {
String url = params[0];
String result = doGetStringFromUrl(url); // You can write your own method;
return result;
}
#Override
protected void onPostExecute(String result) {
mListener.complete(result);
}
#Override
protected void onPreExecute() {
mListener.loading();
}
public interface ILoadDataListener {
void loading();
void complete(String result);
}
}
In your activity
public class MainActivity extends Activity implements AsyncLoadData.ILoadDataListener {
/// Something...
public void getData() {
new AsyncLoadData(this, this).execute(url);
// or new AsyncLoadData(getBaseContext(), this).execute(url);
}
#Override
public void loading() {
// Do something here when you start download and downloading text
}
#Override
public void complete(String result) {
TextView mTextView = (TextView) findViewById(R.id.your_text_view);
mTextView.setText(result);
// EditText is the same.
}
}

Categories

Resources