I am trying to show an ArrayList in ListView using a RecyclerView. But its giving me error an in onPostExecute method when I pass the ArrayList and the Context.
My code is as follows,
class LoadAlltimeTable extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
JSONHttpClient jsonHttpClient = new JSONHttpClient();
UserModel[] user = jsonHttpClient.Get(ServiceUrl.TiMETABLE, nameValuePairs, UserModel[].class);
if (user.length > 0) {
arrayList= new ArrayList<UserModel>();
for (UserModel product : user) {
final TestModel obj= new TestModel();
obj.setName(product.getName());
newList.add(obj);
runOnUiThread(new Runnable(){
#Override
public void run(){
//update ui here
// display toast here
Toast.makeText(TimeTable.this, "Not Null "+ newList.size()+""+obj.getName(), Toast.LENGTH_SHORT).show();
}
});
}
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(TimeTable.this);
progressDialog.setMessage("Loading----");
progressDialog.show();
}
#Override
protected void onPostExecute(String s) {
progressDialog.dismiss();
//here i am getting error
adapter=new TimeTableAdapter(newList,getApplicationContext());
rv.setAdapter(adapter);
}
}
Here is my adapter code,
public class TimeTableAdapter extends RecyclerView.Adapter<TimeTableAdapter.ContactViewHolder> {
ArrayList<TestModel> list;
Activity activity;
public TimeTableAdapter(ArrayList<TestModel> list, Activity activity) {
this.list = list;
this.activity = activity;
}
}
Try using getActivity() instead of getApplicationContext(). Your code should look like:
adapter = new TimeTableAdapter(newList, getActivity());
Explanation:
You're probably getting an error because your constructor goes like:
public TimeTableAdapter(ArrayList<TestModel> list, Activity activity) {
this.list = list;
this.activity = activity;
}
It needs your ArrayList of objects as well as an activity. However, in your fragment, you go with:
adapter = new TimeTableAdapter(newList, getApplicationContext());
What you are giving it is NOT an activity but your fragment class. This gives off an error (I forgot which one) because you're giving it a fragment class instead of an activity class. Hence, you need to use getActivity() instead of getApplicationContext().
Related
Sorry for asking this but I recently started develop android and new to Java.
Currently I am able to "Toast" onPostExecute results in "BackgroundWorkerLocation.java". What I need is to somehow pass these results back to "MainActivty.java" from where I execute this class.
MainActivity.java
String type = "get_location";
String tLatitude = String.valueOf(latitude);
String tLongitude = String.valueOf(longitude);
BackgroundWorkerLocation backgroundWorkerLocation = new BackgroundWorkerLocation(getApplicationContext());
backgroundWorkerLocation.execute(type, tLatitude, tLongitude);
// I need "Results" here
BackgroundWorkerLocation.java
public class BackgroundWorkerLocation extends AsyncTask<String,Void,String> {
Context context;
BackgroundWorkerLocation(Context ctx){
context = ctx;
}
#Override
protected String doInBackground(String... params) {
// Some background work
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Currently I am able to Toast "RESULT" here
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
}
You'll need to create an interface that you can use as a callback:
interface MyCallback {
void onResult(String result);
}
In your activity you create an anonymous implementation of this callback.
Pass it into your ASyncTask.
String type = "get_location";
String tLatitude = String.valueOf(latitude);
String tLongitude = String.valueOf(longitude);
BackgroundWorkerLocation backgroundWorkerLocation = new BackgroundWorkerLocation(getApplicationContext(), new MyCallback() {
#Override
public void onResult(String result) {
// I need "Results" here
}
});
backgroundWorkerLocation.execute(type, tLatitude, tLongitude);
When the ASyncTask completes, you call the "onResult" method of the callback.
public class BackgroundWorkerLocation extends AsyncTask<String,Void,String> {
Context context;
private final MyCallback myCallback;
BackgroundWorkerLocation(Context ctx, MyCallback myCallback){
context = ctx;
this.myCallback = myCallback;
}
#Override
protected String doInBackground(String... params) {
// Some background work
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Currently I am able to Toast "RESULT" here
myCallback.onResult(result);
}
}
This is how you can share data between two classes.
Note that because the callback implementation is anonymous, it has a reference to your Activity, therefore if your task lives longer than your activity it can cause a memory leak. (your next problem :-))
I'm trying to create ProgressDialog during parsing of JSON objects. So I'm using AsyncTask:
private class JsonUtility extends AsyncTask<String, Void, String> {
//getting activity context like that since outer activity is not enclosing
public JsonUtility(Activity activity){
super();
mActivity = activity;
}
public JsonUtility(){}
#Override
protected void onPreExecute(){
super.onPreExecute();
dialog = ProgressDialog.show(mActivity, "Loading...", "Please wait...", true);
}
#Override
protected String doInBackground(String... params) {
//...operate with JSON
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
dialog.hide();
}
}
and I'm getting information from JSON like that:
public ArrayList<CoursesData> getCourses(Activity activity){
ArrayList<CoursesData> resultArrayList = new ArrayList<>();
try {
JSONArray jArray = new JSONArray(new JsonUtility(activity).execute(coursesUrl).get());
//...and so on
}
activity is passed to JsonUtility when Fragment is created with getActivity():
ArrayList<CoursesData> coursesDatas = parserJson.getCourses(getActivity());
is it correct way to pass activity context from Fragment?
Or probably problem lies somewhere else? This ProgressDialog simply doesn't appear although the loading takes about 2-3 sec.
Please help me to solve this problem.
change mActivity to getParent()... its working for me
I have an Activity with DrawerLayout. I am inflating an Fragment in FrameLayout of this Activity xml file. Xml file contain the GridView inside the LinearLayout.
I apply setOnItemClickListener on this GridView inside the fragment onActivityCreated method.
But on this method I am calling AsyncTask Class of my Activity.
So I am not getting the Context when I call this AsyncTask from my setOnItemClickListener.
Please give me some suggestion how to do it or any alternative if possible.
My Activity
class GetExamList extends AsyncTask<String, String, String>{
Context context;
public GetExamList(Context mContext){
context=mContext;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(context);
pDialog.setMessage("Fetching Test List");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
#Override
protected String doInBackground(String... params) {
exam_id=1;
List<NameValuePair> list = new ArrayList<NameValuePair>();
list.add(new BasicNameValuePair("exam_id", exam_id+""));
JSONObject json = jsonParser.makeHttpRequest(url_exam_list,
"POST", list);
// check for success tag
try {
int success = json.getInt("flag");
Log.d("flag", success+"");
if (success == 1) {
//fetch exam list
JSONArray elist=json.getJSONArray("testdata");
Log.d("flag=1", "in try of HomeExamList");
for (int i = 0; i < elist.length(); i++) {
JSONObject obj=elist.getJSONObject(i);
int testId=obj.getInt("test_id");
String testName=obj.getString("test_name");
Log.d("elist test_id", testId+"");
Log.d("elist test_name", testName);
Test test=new Test();
test.setExam_id(exam_id);
test.setTest_id(testId);
test.setTest_name(testName);
Dao dao=new Dao(context);
dao.open();
boolean check=dao.chechTestIdInTestList(testId);
if(!check) dao.insertTestList(test);
dao.close();
}
} else {
// failed to create product
Toast.makeText(getApplicationContext(), "unsuccessful", 2000).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
pDialog.dismiss();
Intent intent = new Intent(context, ExamList.class);
intent.putExtra("eid", exam_id);
startActivity(intent);
}
}
You need to use getActivity() is alternative of context in fragment base design.
getActivity() Return theActivity` this fragment is currently associated with.
Android docs:
http://developer.android.com/reference/android/app/Fragment.html#getActivity%28%29
((MainActivity) getActivity()) is castable to your Activity.
There are ways to get the context:
If you are in an Activity:
this;//will call your activity's context
getApplicationContext();//will get the whole application context
If you are in a Fragment:
getActivity();//will call the activity context
If you are getting the context inside an inner class ex. Asynctask in a Fragment:
Fragment_class_name.this.getActivity();//explicitly get the reference of your fragment and call the context
If you are getting the context inside an inner class ex. Asynctask in a Activity:
Activity_class_name.this;//explicitly get the reference of your activity context
Edit:
change this:
startActivity(intent);
to this:
context.startActivity(intent);
create private Context mContext;
mContext=getActivity();
now you can use mContext instead of getActivity();
how do I return a List generated in an AsyncTask back to the Activity?
My LoadStringsAsync class:
public class LoadStringsAsync extends AsyncTask<Void, Void, List<String> > {
List<String> str;
#Override
protected void onPreExecute() {
super.onPreExecute();
...
}
#Override
protected List<String> doInBackground(Void... arg0) {
...
get content from the internet
and
fill the list
...
}
#Override
protected void onPostExecute(List<String> str) {
super.onPostExecute(events);
...
}
}
and I need the List back in my Activity to work with it. (No not only to show it in ListView :P)
Any suggestions how to do this? :-)
Thanks so far!
your Activity:
public class YourActivity extends Activity {
private List<String> list = new ArrayList<String>();
public void onCreate(Bundle state) {
//...
}
public void setList(List<String> list) {
this.list = list;
}
private void fireYourAsyncTask() {
new LoadStringsAsync(this).execute();
}
}
AsyncTask:
public class LoadStringsAsync extends AsyncTask<Void, Void, List<String>> {
List<String> str;
private YourAcitivity activity;
public LoadStringsAsync(YourAcitivity activity) {
this.activity = activity;
}
#Override
protected List<String> doInBackground(Void... arg0) {
}
#Override
protected void onPostExecute(List<String> str) {
super.onPostExecute(events);
activity.setList(str);
}
}
If you make your AsyncTask an inner class in your Activity, then onPostExecute will be in the same context as the Activity, and you can use the List as you would anywhere in the Activity.
If you don't make your AsyncTask an inner class in your Activity, then you need to set up a listener to call back to your Activity when the AsyncTask finishes. If you prefer to go that route look at this post.
There is also this post that is similar to your question.
According to the documentation from android link you can use the get method to return computational result. Since your AsyncTask shows that you are returning a List, then you can try the following code in the class you are calling the asynchronous class
List<String> returnedlist=new LoadStringAsync().execute().get();
Hoping this option helps.
Place code that uses the list, or sets it to a variable, inside onPostExecute().
Better run your task from parent Activity like:
public class MyActivity extends Activity{
private List<String> mData = new ArrayList<String>();
private void runTask(){
new LoadStringsAsync(){
#Override
protected void onPostExecute(List<String> str) {
super.onPostExecute(events);
mData.clear();
mData.addAll(str);
}
}.execute();
}
}
You can send your list to a handler inside a Message :
Message msg = Message.obtain();
msg.obj = myList;
handler.sendMessage(msg);
More infos : http://developer.android.com/reference/android/os/Message.html
I have a requirement where i need to parse the content of a URL in JSON format. I am able to do that successfully. But i need to save the contents of the URL in a array list and pass them back to the calling functions. Below is the code snippet of what i am trying to achieve.
#Override
protected ArrayList<String> onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
dialog.dismiss();
return ar; // ar is the arraylist i have created and updated it with the content of the url.
}
But running this gives an error. Can anyone please suggest how i can make this possible. However, when i make the return type of onPostExecute as void and toast the contents, its displaying properly. When i call this after the execute, its returning null even though i have updated the contents in doinbackground(). Hence i am unable to get the return values on arraylist format.
// Calling function
Myadapter.execute();
ArrayList<string> str = new ArrayList<string>();
str = print();
// Here str is getting null
// Called function
public ArrayList<String> print() {
ArrayList<String> names = new ArrayList<String>();
for(int i=0;i<al.size();i++)
{
names.add(al.get(i).getConstituencyName());
}
return names;
}
Use a handler
In your activity
mHandler = new Handler() {
#Override public void handleMessage(Message msg) {
ArrayList s=(ArrayList)msg.obj;
tv.setText("Result = "+s.get(0));
}
};
In your onPostexecute
Message msg=new Message();
msg.obj=ar;
mHandler.sendMessage(msg);
The proper way would be to let your activity implement an interface, and when you instantiate the AsyncTask pass the current activity as a parameter to the constructor. Then in onPostExecute() invoke the callback method defined in the Activity and pass the json result as an argument.
Something like this:
interface OnTaskFinished {
void onTaskFinished(String result);
}
public class MainActivity extends Activity implements OnTaskFinished {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ....
new MyAsyncTask(this).execute();
}
#Override
public void onTaskFinished(String result) {
// Process the json result here how you need.
}
}
And this is how the scheleton of your AsyncTask should look like:
private class MyAsyncTask extends AsyncTask<Void, Void, String> {
private final OnTaskFinished listener;
public MyAsyncTask(OnTaskFinished listener) {
this.listener = listener;
}
// ...
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
listener.onTaskFinished(result);
}
}