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();
Related
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().
I'm making a url request using AsyncTask, and want to display some sort of progress spinner while the request is processed. The AsyncTask class is located within another Activity VerificationActivity which extends Activity. The app crashes on this line: dialog = new ProgressDialog(context); Probably the problem is with the context of the app, I tried VerificationActivity.this and creating a local instance of VerificationActivity and passing it as a context.
SmsTask smsTask = new SmsTask(VerificationActivity.this);
/*
* some code
*/
class SmsTask extends AsyncTask<String,Void, Boolean> {
final AtomicBoolean b = new AtomicBoolean(false);
private Context mContext;
ProgressDialog pd;
SmsTask(Context context){
this.mContext = context;
}
#Override
protected void onPreExecute(){
super.onPreExecute();
pd = new ProgressDialog(mContext);
pd.setProgressStyle(AlertDialog.THEME_HOLO_DARK);
pd.show(mContext,"Please wait","Sending...");
}
protected Boolean doInBackground(String... params) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(params[0]);
try {
httpclient.execute(httppost);
b.set(true);
} catch (IOException e) {
e.printStackTrace();
}
return b.get();
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
// result holds what you return from doInBackground
if(pd.isShowing()){
pd.dismiss();
}
Log.i("result from async: ",""+result);
}
}
This is the error message I'm getting:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources$Theme android.content.Context.getTheme()' on a null object reference
UPDATE:
I fixed the context issue based on the answers here, and ran a test, simulated some heavy work inside the doInBackground method using the Thread.sleep() method, but the progress spinner still doesnt show. Any ideas?
UPDATE2:
I managed to show the progress dialog as i need, but now im not able to dismiss it. I assume it is because I cant dismiss UI elements, do i need to run the progress dialog inside runOnUIThread?
I assume you pass the activity as context and by the time the task is going to be executed, the activity might be gone and the you'll get NullPointerException, so 2 options you have;
Check for the context- of it's null you might not need the loading dialog at all
Use the Application context
Hi please see below the updated AsynTas.
class SmsTask extends AsyncTask<String,Void, Boolean> {
final AtomicBoolean b = new AtomicBoolean(false);
private Context mContext;
private ProgressDialog dialog;
private SmsTask(Context context){
this.mContext = context;
}
#Override
protected void onPreExecute(){
super.onPreExecute();
Log.i("executing Pre - execute","");
dialog = new ProgressDialog(mContext );
dialog.setMessage("Loading...");
dialog.show();
}
protected Boolean doInBackground(String... params) {
//.... dosing stuff
return b.get();
}
#Override
protected void onPostExecute(Boolean result) {
if(dialog.isShowing()){
dialog.dismiss();
}
super.onPostExecute(result);
}
}
private Context context;
you have defined context here, but you didn't initialize it. You can initialize it by a constructor
public SmsTask(Context con){
context = con;
}
and when you call your SmsTask pass context to it.
You need to get the application context -
dialog = new ProgressDialog(getContext());
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 implemented a FragmentPagerAdapter of 4-lashes, and in each of them I load a fragment with a different view. In one of them, pressing an image executed a AsyncTask to obtain a series of data from a server and loads a new class through an intent on the onPostExecute() method.
I had this functionality in one activity and worked perfectly. Now to make the call from the fragment I have to make calls using a static mode of this class and I get error in the line of code 'startActivity(i)':
//AsyncTask
private static class CargarJSON extends AsyncTask<String, Void, String> {
Context mContext;
public CargarJSON(Context context) {
mContext = context;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
mProgressItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
mProgressItem.setVisible(true);
mProgressItem.setActionView(R.layout.actionbar_indeterminate_progress);
mProgressItem.expandActionView();
}
#Override
protected String doInBackground(String... params) {
String url = params[0];
String data = MetodosJSON.getHttpResponse(url);
MetodosJSON.parseaJSON2(data, IniSelCategoria.ac);
return params[1];
}
#Override
protected void onPostExecute(String titulo) {
super.onPostExecute(titulo);
// start new activity
Intent i = new Intent(mContext, PantallaInfo.class);
i.putExtra("title", titulo);
i.putExtra("URLser", urlSer);
**startActivity(i);**
mProgressItem.setVisible(false);
}
}
The mistake is:
Cannot make a static reference to the non-static method startActivity(Intent) from the type Activity
How do I make the method call 'startActivity(i)'?
Thank you very much.
Change it to
mContext.startActivity(i);
You need to use a context to call that method if not calling from an Activity. Luckily you are already passing a Context to the constructor.
Change your code with the below one.
Intent i = new Intent(mContext, PantallaInfo.class);
i.putExtra("title", titulo);
i.putExtra("URLser", urlSer);
mContext.startActivity(i); // call using Context instance
I have an application where I have a separate class named "Images1" which extends AsyncTask, where in I am fetching all the gallery URL via JSON.I am instantiating the AsyncTask class in another activity where I need the arraylist returned by the "Images1" class.However I am unable to get the arraylist. Please suggest what steps should be taken.Thanks in advance
public class Images1 extends AsyncTask<Void, Void, ArrayList<String>> {
ProgressDialog mPreogressDialog;
private static String url = "http://www.tts.com/album_pro/array_to_encode";
JSONParser jParser = new JSONParser();
ArrayList<String> image_urls = new ArrayList<String>();
#Override
protected void onPreExecute() {
mPreogressDialog = ProgressDialog.show(Images1.this, "", "Uploading Document. Please wait...", true);
}
#Override
protected ArrayList<String> doInBackground(Void... params) {
// TODO Auto-generated method stub
//Do your stuff here call ur methods
imagedownload();
return image_urls;
}
protected void onPostExecute(ArrayList<String> result) {
super.onPostExecute(result);
// TODO Auto-generated method stub
if (mPreogressDialog.isShowing())
mPreogressDialog.dismiss();
}
public void imagedownload(){
JSONObject json = jParser.getJSONFromUrl(url);
try{
JSONObject seo = json.getJSONObject("SEO");
JSONArray folio = seo.getJSONArray("Folio");
JSONArray image_urls1 = new JSONArray();
String s1=seo.getString("Folio");
for(int i=0;i<folio.length();++i)
{
String m = folio.getString(i);
Log.v("M"+i,m);
image_urls.add(m+ ",");
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
In the another activity I am instantiating the class and calling it as
Images1 img1;
new img1.execute();
I am unable to get the arraylist.
to get result back in Activity where u are starting AsyncTask u will need to execute AsyncTask as :
ArrayList<String> image_urls=new Images1.execute(params_).get();
but this will block UI Thread execution until AsyncTask doInBackground method execution complete. use Thread to execute AsyncTask if u are using AsyncTask.get() method to avoid UI freezing
Second way is pass Activity Context to Images1 class using class constructor and do your work inside onPostExecute. for example :
public class Images1 extends AsyncTask<Void, Void, ArrayList<String>> {
//...your code here..
Context context;
public Images1(Context context){
this.context=context;
}
////....your code here....
protected void onPostExecute(ArrayList<String> result) {
super.onPostExecute(result);
// TODO Auto-generated method stub
// do your work here...
}
}
use context for accessing or updating UI from onPostExecute
You can use Messages and Handlers here. Take a look at this article: http://mobileorchard.com/android-app-developmentthreading-part-1-handlers/. You can send a message from another thread, containing ArrayList. And then handle this message in handleMessage() function of your activity.
I will suggest you one thing just take new Arraylist and make a for loop and add all the values of the image_urls in that list on the onPostExecute Method of AsyncTask class and call that arraytlist.
Another option is to extend this AsyncTask. Call following piece of code in your activity:
new Images1() {
protected void onPostExecute(ArrayList<String> result) {
super.onPostExecute(result);
//here you process received result
}
}.execute();