Issue
I'm doing a list with the download from AsyncTask.
All is well, only when i'm exit from the application and re-launch it, list increases by 2 times = AsyncTask works twice when i'm start Activity. Can I somehow run it 1 time and generally make it static so that it is not attached to Activity?
public class SpecialtyListActivity extends AppCompatActivity {
private static final String URL = "URL..";
public static ArrayList<Specialty> specialtyList = new ArrayList<>();
public static ArrayList<Worker> workerList = new ArrayList<>();
ListView listView;
EmployeesListFragment employeesListFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.specialty_list);
listView = findViewById(R.id.spec_list);
employeesListFragment = new EmployeesListFragment();
if (Utils.isNetworkAvailable(this)) {
new DataLoader(this).execute(URL);
} else {
Toast.makeText(this, "No Network Connection", Toast.LENGTH_LONG).show();
}
}
@SuppressLint("StaticFieldLeak")
class DataLoader extends AsyncTask<String, Void, Void> {
@SuppressLint("StaticFieldLeak")
private Context mContext;
private ProgressDialog pdialog;
private final String TAG = getClass().getSimpleName();
DataLoader(Context context) {
mContext = context;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
pdialog = ProgressDialog.show(mContext, "__", "___");
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
if (mContext != null) {
SpecialtyListAdapter adapter = new SpecialtyListAdapter(this.mContext, R.layout.specialty_list, specialtyList);
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
pdialog.dismiss();
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
});
}
}
@Override
protected Void doInBackground(String... params) {
try {
HttpHandler sh = new HttpHandler();
String jsonStr = sh.makeServiceCall(params[0]);
try {
JSONObject reader = new JSONObject(jsonStr);
JSONArray response = reader.getJSONArray("response");
for (int i = 0; i < response.length(); i++) {
String workerFName = response.getJSONObject(i).getString("f_name");
String workerLName = response.getJSONObject(i).getString("l_name");
String workerBithday = response.getJSONObject(i).getString("birthday");
String workerAvatarUrl = response.getJSONObject(i).getString("avatr_url");
int workerSpecialtyId = response.getJSONObject(i)
.getJSONArray("specialty")
.getJSONObject(0)
.getInt("specialty_id");
String specialtyName = response.getJSONObject(i)
.getJSONArray("specialty")
.getJSONObject(0)
.getString("name");
Specialty specialty = new Specialty(workerSpecialtyId, specialtyName);
if (!specialtyList.contains(specialty)) {
specialtyList.add(specialty);
}
Worker worker = new Worker(workerFName, workerLName);
worker.setBithday(workerBithday);
worker.setAvatarLink(workerAvatarUrl);
worker.setSpecialty(workerSpecialtyId);
workerList.add(worker);
}
} catch (final JSONException e) {
Log.e(TAG, "Json parsing error: " + e.getMessage());
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
I also read that AsyncTask should be static, how to do that?
Solution
I also read that AsyncTask should be static, how to do that?
Nowhere does it say that AsyncTask
should be static. But it is true that since you have made your DataLoader
class an inner class of SpecialtyListActivity
, you can have a slight performance edge by making your inner DataLoader class a static class. Simply add the static modifier:
static class DataLoader extends AsyncTask<String, Void, Void>
like so to the class definition to make it static.
You seem to be under the impression that the reason the DataLoader
AsyncTask fires twice is because it's somehow "attached" to your activity. You can refer the Activity lifecycle for more information about that.
Can I somehow run it 1 time and generally make it static so that it is not attached to Activity?
You can make your AsyncTask a separate class and not an inner class or the activity. (But this will not solve your problem of it firing twice because the reason it's firing twice is not because it's "attached to the activity"). Use the following pattern to make your AsyncTask loosely coupled from your activity.
Make the third generic type of the DataLoader of the type you want as a result from your AsyncTask, in your case that would be ArrayList<Worker>
//Third generic type is ArrayList<Worker>, this is what you want
//to return to your activity once your AsyncTask completes.
class DataLoader extends AsyncTask<String, Void, ArrayList<Worker>> {
private DataLoadListener mListener;
DataLoader(Context context, DataLoadListener listener) {
mContext = context;
mListener = listener;
}
@Override
protected ArrayList<Worker> doInBackground(String... params) {
//download data...
ArrayList<Worker> workersToReturn = new ArrayList<>();
for (int i = 0; i < response.length(); i++) {
//build worker object...
workersToReturn.add(worker);
}
return workersToReturn;
}
@Override
protected void onPostExecute(ArrayList<Worker> result) {
listener.onDataLoaded(billItem);
}
//Your activity should implement this interface and override onDataLoaded() to
//to receive the result when this AsyncTask completes.
public interface DataLoadListener {
void onDataLoaded(ArrayList<Worker> workers);
}
}
public class SpecialtyListActivity extends AppCompatActivity implements DataLoader.DataLoadListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
//Pass both context and DataLoadListener to the constructor
new DataLoader(this, this).execute(URL);
}
@Override
public void onDataLoaded(ArrayList<Worker> workers) {
listView.setAdapter(new SpecialtyListAdapter(context, layout, specialtyList));
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
//Do other stuff
}
}
Also see How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class?
As for your AsyncTask firing twice, you could add a breakpoint to doInBackground method and debug the application. Look at the call stack to figure out why it's being called twice.
Answered By - PrashanD
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.