Android - Get object from AsyncTask result - java

I want to create 10 Employee objects in an AsyncTask and return the result back to the MainActivity class to print it on a ListView with the 3 attributes of an Employee object.
This is what i have so far, but it just crashes after running
Menu class
public class Menu
{
public Employee person;
public void onButtonClick(View v) {
new setEMPInfo() {
protected void onPostExecute(Employee person)
{
doSomething(person);
}
}.execute();
}
public void doSomething(Employee person) {
//use person object to print on TextView
}
}
setEMPInfo class
public class setEMPInfo extends AsyncTask<Void, Void, Employee>
{
Public Employee person;
protected Bus doInBackground(String... params) {
String id = "100A";
String Fname = "John";
String Lname = "Smith";
for (int i = 0; i < 10; i++) {
person = new Employee(id, Fname, Lname);
}
return person;
}
}

Try this :
public class TestActivity extends Activity {
ListView list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
list = (ListView) findViewById(R.id.list_item);
setEMPInfo task = new setEMPInfo().execute();
}
private class setEMPInfo extends AsyncTask<Void, Void, ArrayList<Employee>> {
#Override
protected ArrayList<Employee> doInBackground(Void... params) {
String id = "100A";
String Fname = "John";
String Lname = "Smith";
ArrayList<Employee> employees = new ArrayList<>();
for (int i = 0; i < 10; i++) {
person = new Employee(id, Fname, Lname);
employees.add(person);
}
return employees;
}
#Override
protected void onPostExecute( ArrayList<Employee>result)
//print it on a ListView
list.setAdapter(new YourAdapret(getApplicationContext(), result));
}
}
}

when your doInBackground done , its return some value to onPostExecute . then you can do anything (save in database , save in SDcard , etc) in this method .

You have here an example of a complete asyncTask (by google docs).
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
You can create a static object in your caller class and change it in onPostExecute for example.

The problem is that your class setEMPInfo extends AsyncTask<Void, Void, Employee> and not AsyncTask<String, Void, Bus>
The fix is to change (inside your setEMPInfo class)
protected Bus doInBackground(String... params) { ... }
to
protected Employee doInBackground(String... params) { ... }
and
public class setEMPInfo extends AsyncTask<Void, Void, Employee>
to
public class setEMPInfo extends AsyncTask<String, Void, Employee>
Also, don't forget the #Override annotation.
Finally, I recommend you use an IDE to automatically fix your code spelling and other common mistakes. This problem wouldn't happen in Android Studio or Eclipse. :)
So basically, your code should look like that :
SetEMPInfo.java
public class SetEMPInfo extends AsyncTask<String, Void, Employee>
{
public Employee person;
#Override
protected Employee doInBackground(String... params)
{
String id = "100A";
String Fname = "John";
String Lname = "Smith";
person = new Employee(id, Fname, Lname);
return person;
}
}
Menu.java
public class Menu
{
public Employee person;
public void onButtonClick(View v)
{
new SetEMPInfo()
{
#Override
protected void onPostExecute(Employee employee)
{
doSomething(employee);
}
}.execute();
}
public void doSomething(Employee person)
{
//use person object to print on TextView
}
}

Try this
btnAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new setEMPInfo() {
protected void onPostExecute(Employee person) {
doSomething(person);
}
}.execute();
}
}
);
here just for testing add all employee to list-
public void doSomething(Employee person) {
eList.add(person);
Log.e("Emp->", eList.toString());
}
Your AsyncTask should look like this-
class setEMPInfo extends AsyncTask<Employee, Void, Employee> {
Employee person;
#Override
protected Employee doInBackground(Employee... params) {
String id = "100A";
String Fname = "John";
String Lname = "Smith";
for (int i = 0; i < 10; i++) {
person = new Employee(id, Fname, Lname);
}
return person;
}
}

Related

Passing a variable between functions

I'm new to android studio and Java. My app uses jsoup to pass the contents of a website into an array where each element gets displayed on swipable flashcards (like tinder)
I've got a problem where my app crashes when I try to pass the result of the variable 'words' from onPostExecute() (line 123) to String num on line 49. I want to take the output of the function in onPostExcecute and set it as String num but I'm not sure how to do it.
public class AppHome extends AppCompatActivity implements PopupMenu.OnMenuItemClickListener {
TextView texx;
private ArrayList<String> al;
private ArrayAdapter<String> arrayAdapter;
private int i;
String words;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_app_home);
texx= findViewById(R.id.text1);
new doit().execute();
String num = words;
String str[] = num.split(",");
final ArrayList al = new ArrayList<String>(Arrays.asList(str));
arrayAdapter = new ArrayAdapter<>(this, R.layout.item, R.id.helloText, al );
SwipeFlingAdapterView flingContainer = (SwipeFlingAdapterView) findViewById(R.id.frame);
registerForContextMenu(flingContainer);
flingContainer.setAdapter(arrayAdapter);
flingContainer.setFlingListener(new SwipeFlingAdapterView.onFlingListener() {
#Override
public void removeFirstObjectInAdapter() {
// this is the simplest way to delete an object from the Adapter (/AdapterView)
Log.d("LIST", "removed object!");
al.remove(0);
arrayAdapter.notifyDataSetChanged();
}
#Override
public void onLeftCardExit(Object dataObject) {
//Do something on the left!
//You also have access to the original object.
//If you want to use it just cast it (String) dataObject
Toast.makeText(AppHome.this, "left", Toast.LENGTH_SHORT).show();
}
#Override
public void onRightCardExit(Object dataObject) {
Toast.makeText(AppHome.this, "right", Toast.LENGTH_SHORT).show();
}
#Override
public void onAdapterAboutToEmpty(int itemsInAdapter) {
// Ask for more data here
al.add("XML ".concat(String.valueOf(i)));
arrayAdapter.notifyDataSetChanged();
Log.d("LIST", "notified");
i++;
}
#Override
public void onScroll(float scrollProgressPercent) {
}
});
}
public class doit extends AsyncTask<Void,Void,Void> {
//String words;
#Override
protected Void doInBackground(Void... voids) {
try {
Document doc = Jsoup.connect("https://screenscrape4top40.000webhostapp.com/").get();
words=doc.text();
}catch(Exception e){e.printStackTrace();}
return null;
}
#Override
public void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
texx.setText(words);
//String str = (words);
//List<String> elephantList = Arrays.asList(str.split(","));
//texx.setText(elephantList.toString());
// texx.setText(elephantList);
}
}
}
public class doit extends AsyncTask<Void, Void, String> {
#Override
protected Void doInBackground(Void... voids) {
String words = "";
try {
Document doc = Jsoup.connect("https://screenscrape4top40.000webhostapp.com/").get();
words = doc.text();
} catch(Exception e) {
e.printStackTrace();
}
return words;
}
#Override
public void onPostExecute(String words) {
super.onPostExecute(aVoid);
texx.setText(words);
//String str = (words);
//List<String> elephantList = Arrays.asList(str.split(","));
//texx.setText(elephantList.toString());
// texx.setText(elephantList);
}
}
It should be fine now.
The problem is, you are not returning anything from the doInBackground method and hence you are not getting anything in the onPostExecute function.
You might consider checking the documentation for AsyncTask here.
In doInBackgroud() return the string(make sure it never beacome null) you want to use it on PostExecute()
also changed the data type of Parameter in onPostExecute method
onPostExecute(String Strs)
Then pass it to supper.OnPostExecute().
then u can use it.

Get returned value of interface method

I have implemented this interface:
public interface Callback {
public abstract ArrayList<String> done(ArrayList<Document> docs);
}
Also this method:
public void getNearUsers(Callback callback, LatLng loc) {
new GetNearUsersASyncTask(callback, loc).execute();
}
public class GetNearUsersASyncTask extends AsyncTask<Void, Void, ArrayList<Document>>{
Callback callback;
LatLng loc;
ArrayList<Document> documents;
public GetNearUsersASyncTask(Callback callback, LatLng loc){
this.callback=callback;
this.loc=loc;
documents = new ArrayList<>();
}
#Override
protected ArrayList<Document> doInBackground(Void... params) {
...
return documents;
}
#Override
protected void onPostExecute(ArrayList<Document> docs) {
...
callback.done(docs);
super.onPostExecute(docs);
}
}
And finally this one:
public ArrayList<String> gotoRec() {
final ArrayList<String> finalPostIDs = new ArrayList<>();
serverRequest.getNearUsers(new Callback() {
#Override
public ArrayList<String> done(ArrayList<Document> users){
...
return finalPostIDs;
}
}, loc);
}
});
//return the finalPostIDs of override method;
}
My question is this:
How can i have the finalPostIDs returned ArrayList of Callback interface to return it in gotoRec method ? Is there a way or should i take another road ?

Passing multiple values to AsyncTask class

I am having some problem when trying to pass a String and object to AsyncTask class. So when my button on click, it should pass in a String and an EventReview object into the AsyncTask class:
viewDtlEventBtn.setOnClickListener(new OnClickListener(){
public void onClick(View v){
new GetEventDetailAsyncTask(new GetEventDetailAsyncTask.OnRoutineFinished() {
public void onFinish() {
//Get the values returned from AsyncTask and pass it to another activity
}
}).execute(String.valueOf(eventIDTV.getText()));
}
});
And inside my AsyncTask class, I am getting String as the parameter:
public static class GetEventDetailAsyncTask extends AsyncTask<String, Integer, Double> {
EventController eventCtrl = new EventController();
Context context;
public interface OnRoutineFinished { // interface
void onFinish();
}
private OnRoutineFinished mCallbacks;
public GetEventDetailAsyncTask(OnRoutineFinished callback) {
mCallbacks = callback;
}
public GetEventDetailAsyncTask() {
} // empty constructor to maintain compatibility
public GetEventDetailAsyncTask(Context context){
this.context = context;
}
#Override
protected Double doInBackground(String... params) {
try {
eventCommentModel = eventCtrl.getEventCommentByID(params[0]);
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Double result) {
if (mCallbacks != null)
mCallbacks.onFinish(); // call interface on finish
}
protected void onProgressUpdate(Integer... progress) {
}
}
So I wonder is there any possible way to pass in a String and EventReview object to the execute() and then when doInBackground(), each execute each method. Any guides?
Thanks in advance.
You can pass String and your custom class' object in Object[] in asynctask.
Object[] obj = new Object[2];
obj[0] = "my data";
obj[1] = myEventReviewObj;
new GetEventDetailAsyncTask().execute(obj);
AsyncTask:
public static class GetEventDetailAsyncTask extends AsyncTask<Object, Integer, Double> {
#Override
protected Double doInBackground(Object... params) {
String paramStr = "";
EventReview eventReview = null;
if(params[0] instanceof String && params[1] instanceof EventReview) {
paramStr = (String) params[0];
eventReview = (EventReview) params[1];
}
else {
eventReview = params[0];
paramStr = params[1];
}
try {
//perform operation using String and Object as per your need
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
}
Hope this helps.
You can change the class to accept Objects as input:
public static class GetEventDetailAsyncTask extends AsyncTask<Object, Integer, Double>
and check if the object is an instance of String or of EventReview
#Override
protected Double doInBackground(Object... params) {
if(params[0] instanceof String) // it is String
else if(params[0] instanceof EventReview) // it is EventReview
}
Create custom constructor and save the passed variables in your AsyncTask:
public static class GetEventDetailAsyncTask extends AsyncTask<String, Integer, Double> {
EventReview eventReview;
private OnRoutineFinished mCallbacks;
String string;
Context context;
public GetEventDetailAsyncTask(OnRoutineFinished callback, String str, EventReview review) {
mCallbacks = callback;
string = str;
eventReview = review;
}
...
}
And then call the AsyncTask by passing your vars:
public void onClick(View v){
new GetEventDetailAsyncTask(
new GetEventDetailAsyncTask.OnRoutineFinished() {
public void onFinish() {
// Get the values returned from AsyncTask and pass it to another activity
}
},
String.valueOf(eventIDTV.getText(),
eventReview).execute());
}

Add database connection inside asynctask Android

I'm trying to add a database connection inside my asynctask. This the code I'm working on:
DailySync.class:
DownloadSupplierMaster objAsyncTask;
// TODO get all checked items
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.daily_synchronize);
initControls();
objAsyncTask = new DownloadSupplierMaster(this);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.dailysync_menu, menu);
final MenuItem itemSync;
itemSync = menu.findItem(R.id.sync);
itemSync.setOnMenuItemClickListener(new OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
StringBuffer responseText = new StringBuffer();
responseText.append("Selected modules are...\n");
ArrayList<SyncDataItems> itemList = dataAdapter.itemList;
for (int i = 0; i < itemList.size(); i++) {
SyncDataItems itemName = itemList.get(i);
if (itemName.isSelected()) {
responseText.append("\n" + itemName.getItem() );
}
}
objAsyncTask.execute();
return true;
}
});
return super.onCreateOptionsMenu(menu);
}
#Override
public void onTaskComplete(String result) {
}
DownloadTask.class:
public class DownloadTask extends AsyncTask<Void, Void, Void> {
private Activity activity;
private AsyncTaskListener callback;
public DownloadSupplierMaster(Activity act) {
this.activity = act;
this.callback = (AsyncTaskListener)act;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
protected Void doInBackground(Void...params) {
arraylist = new ArrayList<HashMap<String, String>>();
// Retrieve JSON Objects from the given website URL in JSONfunctions.class
String result = JSONFunctions.getJSONfromURL(URL);
try {
JSONArray jr = new JSONArray(result);
HashMap<String, String> map = new HashMap<String, String>();
String[] keys = { SupplierMaster.TAG_SUPPLIERCODE, SupplierMaster.TAG_SUPPLIERNAME,
SupplierMaster.TAG_SUPPLIERGROUP, SupplierMaster.TAG_SUPPLIERTYPE,
SupplierMaster.TAG_SUPPLIERADDRESS, SupplierMaster.TAG_SUPPLIERADDRESSALT, SupplierMaster.TAG_PHONE1,
SupplierMaster.TAG_PHONE2, SupplierMaster.TAG_FAX,
SupplierMaster.TAG_EMAIL, SupplierMaster.TAG_WEBSITE,
SupplierMaster.TAG_EXPENSEACCOUNT, SupplierMaster.TAG_CONTACTPERSON,
SupplierMaster.TAG_CREDITLIMIT, SupplierMaster.TAG_TOTALCREDIT, SupplierMaster.TAG_TIN,
SupplierMaster.TAG_TAXCODE, SupplierMaster.TAG_TERMS };
for(int i=0;i<jr.length();i++) {
jb = (JSONObject)jr.get(i);
for (String key : keys) {
map.put(key, jb.getString(key));
}
arraylist.add(map);
String suppliercode = jb.getString(SupplierMaster.TAG_SUPPLIERCODE);
String suppliername = jb.getString(SupplierMaster.TAG_SUPPLIERNAME);
String suppliergroup = jb.getString(SupplierMaster.TAG_SUPPLIERGROUP);
String suppliertype = jb.getString(SupplierMaster.TAG_SUPPLIERTYPE);
String supplieraddress = jb.getString(SupplierMaster.TAG_SUPPLIERADDRESS);
String supplieraddressalt = jb.getString(SupplierMaster.TAG_SUPPLIERADDRESSALT);
String phone1 = jb.getString(SupplierMaster.TAG_PHONE1);
String phone2 = jb.getString(SupplierMaster.TAG_PHONE2);
String fax = jb.getString(SupplierMaster.TAG_FAX);
String email = jb.getString(SupplierMaster.TAG_EMAIL);
String website = jb.getString(SupplierMaster.TAG_WEBSITE);
String expenseaccount = jb.getString(SupplierMaster.TAG_EXPENSEACCOUNT);
String contactperson = jb.getString(SupplierMaster.TAG_CONTACTPERSON);
String creditlimit = jb.getString(SupplierMaster.TAG_CREDITLIMIT);
String totalcredit = jb.getString(SupplierMaster.TAG_TOTALCREDIT);
String tin = jb.getString(SupplierMaster.TAG_TIN);
String taxcode = jb.getString(SupplierMaster.TAG_TAXCODE);
String terms = jb.getString(SupplierMaster.TAG_TERMS);
context.dbConnect(); // I'M GETTING A NULLPOINTEREXCEPTION IN THIS LINE!!!!!!!!!!!!
dbHelper.insertORReplaceToSUPPLIERCARD(suppliercode, suppliername, suppliergroup,
suppliertype, supplieraddress, supplieraddressalt, phone1,
phone2, fax, email, website, expenseaccount, contactperson,
creditlimit, totalcredit, tin, taxcode, terms);
dbHelper.close();
}
} catch (JSONException e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void args) {
callback.onTaskComplete("Test");
}
AysncTaskListener.class:
public interface AsyncTaskListener {
public void onTaskComplete(String result);
}
The problem is, I'm getting a nullpointerexception in context.dbConnect();
What do you think is the problem? Any ideas? I would gladly appreciate your help. Thanks.
Where is this context object coming from? Can you confirm that it has a value?
From a design perspective, I suggest creating a database helper class that is a singleton, that you can then access from the AsyncTask and let it handle the database interactions for the whole application as this will both be easier to handle these sorts of exceptions as well as make it very easy to maintain all the database related code for your app.

Retrieve context in an abstract, non activity class

I'm trying to build my abstract implementation of AsyncTask and I would like to insert a custom ProgressDialog. How can I get the context outside of an Activity Class?
abstract public class DataPoller extends AsyncTask<Void, Void, Void> {
Context mContext = getApplicationContext();
ProgressDialog dialog = new ProgressDialog(mContext);
#Override
protected void onPreExecute() {
dialog.setMessage("Polling data...");
dialog.show();
}
#Override
protected void onPostExecute(Void unused) {
if ( dialog.isShowing() ) {
dialog.dismiss();
}
}
#Override
protected Void doInBackground(Void... params) {
int tmp=0;
for (int ii = 0; ii<1000; ii ++) {
for (int jj = 0; jj<1000; jj ++) {
tmp = ( tmp + 3 ) % 167;
}
}
return null;
}
}
You could pass it into the constructor:
abstract public class DataPoller extends AsyncTask<Void, Void, Void> {
...
Context mContext;
...
DataPoller(Context context){
super();
this.mContext = context;
}
...
}

Categories