I have following code in which I want to pass the context as a first parameter but I cant , tried all possible answers from net such as : getActivity(), getContext(), this , getActivity().getApplicationContext()
Nothing works and my app crashes because of exception :| My Class is extended from fragment
public void onClick(View v) {
HashMap postData = new HashMap();
PostResponseAsyncTask task = new PostResponseAsyncTask(this,postData);
task.execute("http://ashna.netau.net/A_location.php");
}
Your function onClick() is probably inside an object implementing the interface View.OnClickListener which contains no functions like getActivity() or getContext().
Try the following:
final Context context = getActivity();
View.OnCLickListner mListener = new View.OnClickListener() {
public void onClick(View v) {
HashMap postData = new HashMap();
PostResponseAsyncTask task = new PostResponseAsyncTask(context,postData);
task.execute("http://ashna.netau.net/A_location.php");
}
}
you can create application class and create a global instance of the application variable inside in it. So you can have the access to the application context from anywhere in the app.
Try this:
PostResponseAsyncTask task = new PostResponseAsyncTask(v.getContext(),postData);
Related
The following code is leaking the activity context:
This is actually inside an asyncTask in the onPostExecute
ChatCustomAdapter customAdapter = new ChatCustomAdapter(mContext, chatData, Typeface.createFromAsset(getAssets(), "font/Helvetica-Bold.ttf"));
mChatList.setAdapter(customAdapter);
inside the adapter the context is used for
inflater = LayoutInflater.from(mContext);
Am I holding a reference to the context? if so how do I release it?
LeakCanary is telling me that the ListView (mChatList) is leaking the context and if i remove setAdapter the leak has gone.
EDIT:
You can try to wrap your mChatList with WeakReference, for exp:
class ChatTask extends AsyncTask {
private WeakReference<ListView> mListRef;
public ChatTask(ListView chatList) {
mListRef = new WeakReference<ListView>(chatList);
}
public void onPostExecute() {
ListView chatList = mListRef.get();
if (chatList != null) {
Context context = chatList.getContext();
ChatCustomAdapter customAdapter = new ChatCustomAdapter(context, chatData,
Typeface.createFromAsset(context.getAssets(), "font/Helvetica-Bold.ttf"));
chatList.setAdapter(customAdapter);
}
}
}
If it still not work, you could try to follow this post
I assume that you create the inflater inside the ChatCustomAdapter constructor and keep that inflater as global variable to use later in getView method?
If that true, I think you should try to remove the variable inflater and inside getView method, create a local inflater by LayoutInflater.from(parentView.getContext);
Hope that helps.
ok so i have found the problem but i do not understand it so maybe some can comment and explain or answer with why it does this. the leak was in the Chat activity. to get to the Chat activity i have a button in the previous activity:
ChatButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View arg0)
{
Intent intent = new Intent(mContext, Chat.class);
mContext.startActivity(intent);
}
});
when i start the activity i was starting it from
mContext.startActivity(intent)
if i change this to just
startActivity(intent);
it doesn't leak.
Edit
it does still leak
i've already implemented this thing in my application using activity,
refer image link below
"http://imgur.com/LuErJjY"
in the first part you can see the context=PerformanceActivity#4015
but in the 2nd part it is null
the code i've used is
IN ACTIVITY:
viewHolder.nextReview.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
int d=v.getId();
((PerformanceActivity)context).performReview(v.getId());
}
});
IN FRAGMENT:
NOTE: PerformanceFragment pf;
viewHolder.nextReview.setId(resData.get(position).getTestID());
viewHolder.nextReview.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
int d=v.getId();
((PerformanceFragment)pf).performReview_frag(v.getId());
}
});
Both the methods are methods present in the adapter of a listview. In Activity It just works fine, but not in fragment.
Links to both adapters:
https://pastee.org/28chw - Fragment's Adapter https://pastee.org/nw8rr
- Fragment
https://pastee.org/wxepy -Activity's Adapter
At last this worked for me -
PerformanceFragmentAdapter adapter = new PerformanceFragmentAdapter(context,rsuData,device,this);
and adding this to the adapter as
private PerformanceFragment pf;
public PerformanceFragmentAdapter(Context conte, ArrayList<ResultData> rData,
int device, PerformanceFragment pp) {
super();
context = conte;
resData = rData;
size = device;
pf=pp;
}
guess #ursgtm is right. still confusing between Context c=getActivity(); and this keyword
In PerformanceFragmentAdapter class :
PerformanceFragment pf;
You are just creating a object with no instance and you are using that object as context,and you are not assigning anything to pf .
Instead of remove pf, and pass the context which you got from constructor:
viewHolder.nextReview.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
int d=v.getId();
//Replace ((PerformanceFragment)pf) with context
context.performReview_frag(v.getId()); //you obtained context from contractor.
}
});
Hope this helps you !
In second part use getActivity() method if your fragment PerformanceFragment is associated with your activity PerformanceActivity
viewHolder.nextReview.setId(resData.get(position).getTestID());
viewHolder.nextReview.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
int d=v.getId();
/* (getActivity()). no need to use content if
performReview_frag() is present in PerformanceFragment fragment*/
// this will call performReview_frag() method
performReview_frag(v.getId());
}
});
Else,
You can use getBaseContext() method to get correct context
actually I am bit confused on some thing which is working in one scenario very well but in other scenario that is not working fine so I am here to explain my problem to identify the wrong move made by me, if any on will identify the problem please mention it. thank you.
working fine:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.distance_demo_button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, ListViewClass.class);
intent.putExtra(ListViewClass.EXTRAS_TARGET_ACTIVITY, Distance.class.getName());
startActivity(intent);
}
});
NOt working fine:
scan = (Button) view.findViewById(R.id.scan);
scan.setOnClickListener(startListener);
}
//Create an anonymous implementation of OnClickListener
private OnClickListener startListener = new OnClickListener() {
public void onClick(View v) {
Toast.makeText(view.getContext(),"Scanning", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(MainActivity.this, ListViewClass.class);
intent.putExtra(ListViewClass.EXTRAS_TARGET_ACTIVITY, Distance.class.getName());
startActivity(intent);
}
}
now the problem is in this line
Intent intent = new Intent(MainActivity.this, ListViewClass.class);
when I use this line in this scenario it shows me error on this line:
Error: 'The constructor Intent(MainActivity, Class<ListViewClass>) is undefined' please mention my problem if you are well aware of it.
use a global context variable glaboaly and use it.
Context myContext;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myContext = MyActivity.this;
}
and use myContext insted of MainActivity.this.
Im not sure whether it solve the problem, just try it out
When your calling Intent intent = new Intent(MainActivity.this, ListViewClass.class); inside MainActivity class. It will work fine. But when your not in Context of MainActivity class. i.e move to other class. This error will occur.
If you want to rectify, You can follow #jithu method. Otherwise store the context in Application class. And use it in anywhere.
In the first case you are overriding the method onClick().
If you override the method it's like you are declaring the function in your activity class.
This is the reason that you can call MainActivity.this
In the second case you are implementing the abstract method onClick(). You can't call MainActivity.this because your "MainActivity.this" is referencing to the current context and this isn't accessible from OnClickListener.class.
First of all, I'm well aware that this error is occur because I'm trying to call window/dialog through a Context that is not an Activity.
But isn't there any solution to that. My requirements are; I have a Dialog with a custom style sheet in a method of a normal JAVA class. I want to call that method from any Activity class when I need to load the Dialog.
In my Activity class I'm having following code set;
HomeClass homeClass = new HomeClass();
homeClass.showSplashScreen();
Then in my HomeClass I have following code set;
public void showSplashScreen() {
splashDialog = new Dialog(HomeActivity.getAppContext(), R.style.SplashScreen);
splashDialog.setContentView(R.layout.splash_screen);
splashDialog.setCancelable(false);
splashDialog.show();
}
By maintaining this design, is there any way to get rid of the WindowManager$BadTokenException
Thank You
I am going to modify your code, that maybe helpful for you...
HomeClass homeClass = new HomeClass(this);
homeClass.showSplashScreen();
In Your Home class.. add parametric constructor..
public class Home {
private Context context;
public Home(Context context){
this.context = context;
}
public void showSplashScreen() {
splashDialog = new Dialog(context, R.style.SplashScreen);
splashDialog.setContentView(R.layout.splash_screen);
splashDialog.setCancelable(false);
splashDialog.show();
}
Pass Your Activity to showSplashScreen() Method...
Do like this..
HomeClass homeClass = new HomeClass();
homeClass.showSplashScreen(Your Actvity);
In Your Home class
public void showSplashScreen(Activity curActivity) {
splashDialog = new Dialog(curActivity, R.style.SplashScreen);
splashDialog.setContentView(R.layout.splash_screen);
splashDialog.setCancelable(false);
splashDialog.show();
}
I am trying to build a char using the library from achartengine (http://www.achartengine.org/). So i try to run SalesGrowthChart.java on my own aplication so when someone clicks on a button it will show him the chart .
This is my code :
private IChart[] mCharts = new IChart[]{new generatedchart()};
And i try to generate it like this
bt.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent myIntent = new Intent(view.getContext(), generatedchart.class);
myIntent=mCharts[0].execute(this);
}
});
But this won't work. How can i make it to work.Hope you understand what i am saying.
This is the error :
The method execute(Context) in the type IChart is not applicable for the arguments (new View.OnClickListener(){})
Your problem is that the "this" mentioned inside that method refers to a view (which is what you are creating at that point.)
The method execute needs a Context, so you need to get the context in a different manner.
You should try getting the context like this:
YourActivityName.this
Which in your code would be like:
bt.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent myIntent = new Intent(view.getContext(), generatedchart.class);
myIntent=mCharts[0].execute(YourActivityName.this);
}
});
When you are calling this within execute(), it is referring to the OnClickListener class because of the dynamic class declaration. Try using getApplicationContext() instead of this.