Send string variable from Activity to AsyncTask Class - java

I need to send a string variable from my main activity class to the AsyncTask Class and use that string as part of the url to make the api call.
I tried using Intent and share preferences but neither can seem to be accessed in the AsyncTask Class. Can I use Singleton pattern, and if yes, how would I go about it?

If you declare a global variable:
public class MainActivity extends Activity {
private String url = "http://url.com";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new DownloadFilesTask().execute();
}
private class DownloadFilesTask extends AsyncTask<Void, Void, Void> {
protected Long doInBackground(Void... params) {
// You can use your 'url' variable here
return null;
}
protected void onProgressUpdate(Void... result) {
return null;
}
protected void onPostExecute(Void result) {
}
}
}
if you work in seperate classes:
new MyAsyncTask("Your_String").execute();
private class MyAsyncTask extends AsyncTask<Void, Void, Void> {
public MyAsyncTask(String url) {
super();
// do stuff
}
// doInBackground()
}

Related

Error in implementation of interface between activity and view

I'm trying to get in my MyActivity an int from a View MyView. In my activity I have the following:
public class MyActivity extends AppCompatActivity implements MyView.GetCallBack {
final MyActivity context = this;
private AsyncTask<Void, Void, Void> task;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second_act);
task = new myTask();
task.execute();
}
#Override
public void onPercentageReceived(int msg){
// you have got your msg here.
}
public class MyTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
}
#Override
protected void onPostExecute(Void result) {
LinearLayout surface = (LinearLayout) findViewById(R.id.surfaceView);
surface.addView(new MyView(getApplicationContext()));
surface.setBackgroundColor(Color.BLACK);
}
}
Now MyView contains the following code:
public class MyView extends View {
final MyView context = this;
private GetCallBack callback;
// Constructor
public PlacingBoxView(Context context) {
super(context);
callback = (GetCallBack) context;
}
#Override
protected void onDraw(Canvas canvas) {
dataPercentage(Percentage);
}
public void dataPercentage(int Percentage){
callback.onPercentageReceived(Percentage);
}
public interface GetCallBack{
void onPercentageReceived(int msg);
}
I can compile the code without problems, but in the LogCat I get the following mistake:
FATAL EXCEPTION: main
Process: com.example.ex, PID: 8035
java.lang.ClassCastException: android.app.Application cannot be cast
to com.example.ex.myView$GetCallBack
at com.example.ex.myView.(myView.java:49)
I know the error is related with the Context, but I still haven't found out a way to correct it,
Any idea will be really appreciated! :)
You have implemented the interface in myActivity but you are passing application context. That's why you are getting ClassCastException. Pass myActivity.this, so try like this:
surface.addView(new MyView(MyActivity.this);

Using List Adapter in a Fragment Activity

I have an activity class that extends from FragmentActivity as I am using DialogFragment in it.
Earlier this class was extended from ListActivity and there was no issues but when I extended it from FragmentActivity when the requirement of DialogFragment arrive the method setListAdapter becomes unavaible.
I want to know that how can I use the method setListAdapter while extending my class from FragmentActivity
public class Main extends FragmentActivity{
…
…
private class fetchStudentInfo extends AsyncTask<String, Void, List<mStudentInfo>> {
#Override
protected List<mStudentInfo> doInBackground(String... urls) {
…
}
public void onPostExecute(List<mStudentInfo> StudentInfoCollection) {
setListAdapter(new StudentInfoAdapter((Activity) mainAppContext, StudentInfoCollection));
}
}
}
For setting setAdapter you need a listView reference like this ,
public class Main extends FragmentActivity {
private ListView mListView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout_id);
mListView = (ListView)findViewById(R.id.list);
}
private class fetchStudentInfo extends AsyncTask<String, Void, List<mStudentInfo>> {
#Override
protected List<mStudentInfo> doInBackground(String... urls) {
…
}
public void onPostExecute(List<mStudentInfo> StudentInfoCollection) {
mListView.setListAdapter(new StudentInfoAdapter((Activity) mainAppContext, StudentInfoCollection));
}
}
}
And also you need layout file with a listview inside with id R.id.list.

java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View .MainActivity.findViewById(int)' on a null object reference

I have a class called MainActivity.java that call an AsyncTask class. The last class have a findViewById() that in execution return this error:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View <mypackage>.MainActivity.findViewById(int)' on a null object reference
I don't understand how can I edit an ImageView positioned in R.layout.activity_main after that an AsyncTask finish to work.
MainActivity.java
public class MainActivity extends Activity {
public MainActivity() {}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Connection().execute();
}
}
Connection.java
public class Connection extends AsyncTask<String, Void, String> {
public String result;
//I know, this isn't correct, how can i do?
public MainActivity MainActivity;
#Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
//...
return "a string";
}
protected void onPostExecute(String result) {
super.onPostExecute(result);
//...
// Where the error is generated
ImageView image = (ImageView) MainActivity.findViewById(R.id.image);
//...
}
}
The error is that
public MainActivity MainActivity;
is never initialized, thus pointing to null.
To make your code work the minimum step is
in MainActivity
new Connection(this).execute();
In Connection
public class Connection extends AsyncTask<String, Void, String> {
public MainActivity MainActivity;
public Connection(MainActivity activity) {
MainActivity = activity;
}
But creating a task in onCreate and passing an Activity is not the best idea anyway.
Also, field names should always start with a lowercase letter.
The best way is passing an ImageView to the AsyncTask.
Don't start a task until the Activity is started and also, don't forget to cancel the task when the Activity is stopped.
public final class MainActivity extends Activity {
public MainActivity() {}
private Connection connection;
private ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.image);
}
#Override
protected void onStart() {
super.onStart();
if (connection == null || connection.getStatus() != AsyncTask.Status.RUNNING) {
connection = new Connection(imageView);
connection.execute();
}
}
#Override
protected void onStop() {
super.onStop();
if (connection != null && connection.getStatus() == AsyncTask.Status.RUNNING) {
connection.cancel(true);
}
}
}
In Connection.java, store an ImageView as a WeakReference to avoid leaks.
public final class Connection extends AsyncTask<String, Void, String> {
private final WeakReference<ImageView> imageViewRef;
public Connection(ImageView view) {
imageViewRef = new WeakReference<ImageView>(view);
}
#Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
//...
return "a string";
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
//...
final ImageView imageView = imageViewRef.get();
// if the Activity is still alive, the ImageView will not be null
if (imageView != null) {
// set an image or whatever you need
image.setImageResource(666);
}
}
put imageview as a variable of your class
private ImageView image;
on your onCreate initialize
image = (ImageView) findViewById(R.id.image);
public class Connection extends AsyncTask<String, Void, String> {
public String result;
//I know, this isn't correct, how can i do?
public MainActivity MainActivity;
#Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
//...
return "a string";
}
protected void onPostExecute(String result) {
super.onPostExecute(result);
//...
// Where the error is generated
//do other stuff with your imageview
//...
}
}
You did not specify what parameter you pass to Connection.java AsyncTask.
One of my student is also having same problem.
Although he is using Volley Library for HttpConnection (posting data) and main issue was:
he is writing URL directly without the http protocol prefix i.e.
String post_url ="api/do_post";
Simply add http/https at front of your post url:
String post_url ="http://api/do_post";
actually i was working an activity and service application. same problem i also got,
in that in bindservice i have used the BIND_IMPORTANT flag instead of using BIND_AUTO_CREATE.
once i changed the flag it was worked successfully for me.

How to inject an anonymous inner class with dagger?

It's posible inject an anonymous class? I'm having the following error:
java.lang.IllegalArgumentException: No inject registered for members/com.acme.MyFragment$1. You must explicitly add it to the 'injects' option in one of your modules.
Example:
public class MyFragment extends Fragment {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new MyTrask(getActivity()) {
protected void onPostExecute(String result) {
// Stuff
}
}.execute();
}
}
public class MyTask extends AsyncTask<Void, Void, String> {
#Inject
UserApi userApi;
public MyTask(Context context) {
App.getInstance().inject(this);
}
#Override
protected String doInBackground(Void... params) {
return "Hello World!";
}
}
You should inject the AsyncTask into MyFragment rather than using "new MyTask(..)". The MyTask constructor should take an UserApi instance and a Context object which can be provided by the module with code akin to;
/**
* The application module.
*
* #param context The context.
*/
public MyModule(final Context context) {
this.context = context.getApplicationContext();
}
/**
* Provides context.
*
* #return the application context.
*/
#Provides #Singleton Context provideContext() {
return context;
}
Your fragment code should then look like;
public class MyFragment extends Fragment {
#Inject Provider<MyTask> myTaskProvider;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
inject(this);
myTaskProvider.get().execute();
}
}
And your AsyncTask API should be;
#Inject
public MyTask(Context context, UserApi userApi) { }
Notice I used a Provider for the injection of the AsyncTask. This is necessary to avoid exceptions akin to "You can only execute a task once" that you would get if you called execute against the same AsyncTask object more than once. You then register MyFragment under your module injects = { } annotation arguments.
You can't inject into an anonymous class. But you can do inject into the Fragment and it will be visible for the anonymous class, the AsyncTask in this case.
public class MyFragment extends Fragment {
#Inject
UserApi userApi;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
App.getInstance().inject(this);
new MyTrask() {
protected void onPostExecute(String result) {
// Stuff
}
}.execute();
}
}
public class MyTask extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... params) {
userApi.callAnyMethod(); // use userApi here
return "Hello World!";
}
}

Using ProgressDialog in AsyncTack being called from class extending Application

I extended to Application class with my own data class. It is used to store global objects in my app and make them accessible by all Acitivites. I would like this class, when initialized on application run, to download data from the internet via AsyncTask. How can I show/hide a ProgressDialog within AsyncTask, which requires me to pass the correct Context/Activity to it?
public class DataSource extends Application{
private int userid;
private Object[] orders;
//initialize
#Override
public void onCreate() {
// Pull data from the internet and store it in orders
super.onCreate();
}
public void beginDataLoad(Activity callingActivity) {
// HOW DO I PASS THE CORRECT ACTIVITY TO MY NEW downloadData OBJECT?
downloadData task = new downloadData(callingActivity);
task.execute(new String[] { "http://www.myurl.com" });
}
private class downloadData extends AsyncTask<String, Void, String>{
private ProgressDialog progressDialog;
private MainActivity activity;
public downloadData(MainActivity activity) {
this.activity = activity;
this.progressDialog = new ProgressDialog(activity);
}
protected void onPreExecute() {
progressDialog.setMessage("Downloading events...");
progressDialog.show();
}
protected String doInBackgroun(String... params) {
// Do AsyncTask download functions in background...
}
protected void onPostExecute() {
progressDialog.dismiss();
//Callback function in MainActivity to indicate data is loaded
activity.dataIsLoaded();
}
}
}
I ended up calling the datasource load from my MainActivity this way.
public class MainActivity extends Activity {
//onclick function...
myDataSource = (DataSource)getApplicationContext();
myDataSource.beginDataLoad(MainActivity.this);
//Callback for AsyncTask to call when its completed
public void dataIsLoaded() {
//Do stuff once data has been loaded
}
}

Categories