In onAttach function eclipse shows error stating
The method onAttach(Activity) in the type Fragment is not applicable
for the arguments (Context)
although it is clearly Context type variable passed
import android.content.Context;
public class MyListFragment extends Fragment{
private OnItemSelectedListener listener;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_rsslist_overview,
container, false);
Button button = (Button) view.findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
updateDetail("fake");
}
});
return view;
}
public interface OnItemSelectedListener {
public void onRssItemSelected(String link);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnItemSelectedListener) {
listener = (OnItemSelectedListener) context;
} else {
throw new ClassCastException(context.toString()
+ " must implemenet MyListFragment.OnItemSelectedListener");
}
}
#Override
public void onDetach() {
super.onDetach();
listener = null;
}
// may also be triggered from the Activity
public void updateDetail(String uri) {
// create a string just for testing
String newTime = String.valueOf(System.currentTimeMillis());
// inform the Activity about the change based
// interface defintion
listener.onRssItemSelected(newTime);
}
}
If you are using API < 23 then
public void onAttach(Context context) {
should be
public void onAttach(Activity context) {
See official docs
Note:
onAttach(Context context) was added in api 23. See this
I had same problem can you try to pass Activity in your onAtach method like this:
#Override
public void onAttach(Activity activity) {
super.onAttach(context);
if (context instanceof OnItemSelectedListener) {
listener = (OnItemSelectedListener) activity;
} else {
throw new ClassCastException(context.toString()
+ " must implemenet MyListFragment.OnItemSelectedListener");
}
}
and tell me if it works or not.
Hope to help!
Related
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 4 years ago.
E/UncaughtException: java.lang.NullPointerException: Attempt to invoke interface method 'void mm.com..fragment.BottomSheetFragment$BottomSheetListener.onButtonClicked(java.lang.String)' on a null object reference
at mm.com.blueplanet.videoclip.fragment.BottomSheetFragment$1.onClick(BottomSheetFragment.java:40)
at android.view.View.performClick(View.java:5647)
This is RecycervieAdapter class
((ItemViewHolder) holder).cmtText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentTransaction ft = ((DetailActivity) mContext).getSupportFragmentManager()
.beginTransaction();
BottomSheetFragment bottomsheet= new BottomSheetFragment();
bottomsheet.show( ft, "BottomSheet");
}
});
This is bottomsheet
public class BottomSheetFragment extends BottomSheetDialogFragment {
Context mContext;
public BottomSheetListener mListener;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.custom_bottom_dialog, container, false);
mContext = getActivity();
ImageButton btn = (ImageButton) v.findViewById(R.id.cmt_btn);
final EditText edt = (EditText) v.findViewById(R.id.edt_cmt);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mListener.onButtonClicked("" + edt.getText().toString());
dismiss();
}
});
return v;
}
public interface BottomSheetListener {
void onButtonClicked(String text);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
mListener = (BottomSheetListener) mContext;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString());
}
}
}
((ItemViewHolder) holder).cmtText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentTransaction ft = ((DetailActivity) mContext).getSupportFragmentManager()
.beginTransaction();
BottomSheetFragment bottomsheet= new BottomSheetFragment();
bottomsheet.show( ft, "BottomSheet");
bottomsheet.onButtonClicked()
}
});
you must Implement onButtonClicked when you created new Object
and You can Edit Your Listener like this
private onItemsClicked mListener = null;
and create Two Interface
public void setOnClickListener(onItemsSelected onClickListener)
{
mListener = onClickListener;
}
public interface onItemsSelected
{
void onclick(float x, float y, String value);
}
Now You Can use it Like this
view.setOnClickListener(new LineChart.onItemsSelected() {
#Override
public void onclick(float x, float y , String value) {}
So in my app I have a bunch of fragments that the user navigates through. And there are a lot of methods in my activity class that are used for fragment transitions. These are very similar to each other with the only difference being the class of the newFragment. Here is one these methods:
public void onHelpSelected() {
slideInRight();
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
HelpFragment newFragment = new HelpFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
transaction.commit();
slideOutLeft();
}
}, 500);
}
Then, I also have a few classes that describe each fragment. These are also very similar to each other: they differ only by the amount of buttons and by what these buttons do (but most of the buttons are used for fragment transitions). Here is one of these classes:
public class AuthFragment extends Fragment {
Button authRegButton;
Button authHelpButton;
OnHelpButtonListener helpCallback;
OnRegButtonListener regCallback;
#Override
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_auth, container, false);
authHelpButton = (Button) view.findViewById(R.id.auth_help_button);
View.OnClickListener authHelpListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
helpCallback.onHelpSelected();
}
};
authHelpButton.setOnClickListener(authHelpListener);
authRegButton = (Button) view.findViewById(R.id.auth_reg_button);
View.OnClickListener authRegListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
regCallback.onRegSelected();
}
};
authRegButton.setOnClickListener(authRegListener);
return view;
}
public interface OnHelpButtonListener {
void onHelpSelected();
}
public interface OnRegButtonListener {
void onRegSelected();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
helpCallback = (OnHelpButtonListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement OnHelpButtonListener");
}
try {
regCallback = (OnRegButtonListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement OnRegButtonListener");
}
}
}
So, I have many pieces of code that are very similar. I bet there is a way to make all this code look much nicer and work more efficiently.
Thus, my question is how do I do that? :)
Thanks!
Here is how I solved this problem, if someone ever needs this :)
So I made an abstract class for my fragments and worked out all the code there:
public abstract class LoginFragment extends Fragment {
MediaPlayer clickPlayer;
int layoutId;
View view;
OnButtonListener buttonCallback;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(layoutId, container, false);
return view;
}
public interface OnButtonListener {
void onButtonSelected(LoginFragment fragment);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
buttonCallback = (OnButtonListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement OnButtonListener");
}
}
public MyButton setUpButton(int buttonId) {
final MyButton button = (MyButton) view.findViewById(buttonId);
View.OnClickListener authHelpListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
clickPlayer = MediaPlayer.create(getContext(), R.raw.click);
clickPlayer.start();
LoginFragment newFragment = determineFragment(button);
buttonCallback.onButtonSelected(newFragment);
}
};
button.setOnClickListener(authHelpListener);
return button;
}
public LoginFragment determineFragment(MyButton button) {
LoginFragment result;
int buttonId = button.getId();
switch (buttonId){
case R.id.auth_help_button:
result = new HelpFragment();
break;
case R.id.agr_cancel_button:case R.id.help_cancel_button:
case R.id.reg_cancel_button:case R.id.reg_cont_cancel_button:
result = new AuthFragment();
break;
case R.id.agr_back_button:case R.id.reg_cont_button:
result = new RegContFragment();
break;
case R.id.reg_cont_agr_button:
result = new AgrFragment();
break;
case R.id.auth_reg_button:
result = new RegFragment();
break;
default:
result = null;
break;
}
return result;
}
I'm trying to build an App for Android Lollipop (5.0). There is a login fragment and when i press login button then app automatically crashes. I'm sharing my code and error message please guide me.
BaseActivity.java
public abstract class BaseActivity extends AppCompatActivity {
protected CoreApplication coreApplication;
#Override
protected void onCreate(Bundle savedState) {
super.onCreate(savedState);
coreApplication = (CoreApplication) getApplication();
}
}
BaseAuthenticatedActivity.java
public abstract class BaseAuthenticatedActivity extends BaseActivity {
#Override
protected final void onCreate(Bundle savedState) {
super.onCreate(savedState);
if (!coreApplication.getAuth().getUser().isLoggedIn()) {
startActivity(new Intent(this, LoginActivity.class));
finish();
return;
}
onCoreApplicationCreate(savedState);
}
protected abstract void onCoreApplicationCreate(Bundle savedState);
}
LoginActivity.java
public class LoginActivity extends BaseActivity implements View.OnClickListener, LoginFragment.CallBacks {
private static final int REQUEST_NARROW_LOGIN = 1;
private View loginButton;
#Override
protected void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.activity_login);
loginButton = findViewById(R.id.LoginJustChat);
if (loginButton != null) {
loginButton.setOnClickListener(this);
}
}
#Override
public void onClick(View view) {
if (view == loginButton)
startActivityForResult(new Intent(this, LoginNarrowActivity.class), REQUEST_NARROW_LOGIN);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK)
return;
if (requestCode == REQUEST_NARROW_LOGIN) {
finishLogin();
}
}
private void finishLogin() {
startActivity(new Intent(this, MainActivity.class));
finish();
}
#Override
public void onLoggedIn() {
finishLogin();
}
}
LoginNarrowActivity.java
public class LoginNarrowActivity extends BaseActivity implements LoginFragment.CallBacks {
#Override
protected void onCreate(Bundle savedState){
super.onCreate(savedState);
setContentView(R.layout.activity_login_narrow);
}
#Override
public void onLoggedIn() {
setResult(RESULT_OK);
finish();
}
}
MainActivity.java
public class MainActivity extends BaseAuthenticatedActivity {
#Override
protected void onCoreApplicationCreate(Bundle savedState) {
}
}
BaseFragment.java
public abstract class BaseFragment extends Fragment {
protected CoreApplication application;
#Override
public void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
application = (CoreApplication) getActivity().getApplication();
}
}
LoginFragment.java
public class LoginFragment extends BaseFragment implements View.OnClickListener {
private Button loginButton;
private CallBacks callBacks;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup root, Bundle savedState) {
View view = inflater.inflate(R.layout.fragment_login, root, false);
loginButton = (Button) view.findViewById(R.id.fragment_login_loginButton);
loginButton.setOnClickListener(this);
return view;
}
#Override
public void onClick(View view) {
if (view == loginButton) {
application.getAuth().getUser().setIsLoggedIn(true);
callBacks.onLoggedIn();
}
}
// because onAttach(Activity activity) is deprecated
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof CallBacks) {
callBacks = (CallBacks) context;
} else {
throw new ClassCastException(context.toString()
+ " must implement MyListFragment.OnItemSelectedListener");
}
}
#Override
public void onDetach() {
super.onDetach();
callBacks = null;
}
public interface CallBacks {
void onLoggedIn();
}
}
Error:
java.lang.NullPointerException: Attempt to invoke interface method
'void
com.example.usama.demoapp.fragments.LoginFragment$CallBacks.onLoggedIn()'
on a null object reference
Please guide me with this.
Welcome to Android !
You got a NullPointerException. It's a very common [and lovely; since it's rather easy to debug] exception in Java. Check your LoginFragment. The following method will cause this exception to raise.
#Override
public void onClick(View view) {
if (view == loginButton) {
application.getAuth().getUser().setIsLoggedIn(true);
callBacks.onLoggedIn();
}
}
A couple of notes in order to diagnose this error:
When you declare a class member with initializing it, in this casecallBacks, Java automatically initialize it to null.
Invoking any method on a null reference will result in NPE.
Okay, let's narrow down to your specific case. You declared a class member called callBacks but never initialized it, as well as, I can see no methods that assign something to it. Therefore, that class member always remains null and thereby any subsequent method invocation on it leads us to NPE.
As a solution, you should add a setter method to your LoginFragment class in which you set that callBacks. In other side supply this object where you first create an instance of this fragment.
Update #1
when i pass Activity instead of Context as parameter in onAttach method it works. but i want to know why it is causing the error?
The why is simple. Since your activity already implemented that interface, so passing it to your LoginFragment as context will result in the condition if (context instanceof CallBacks) becoming true. However, passing bare context won't result in establishment of that if statement.
can u please tell me how i can define setter?
It's pretty simple! Just as other regular method, declare a method like this:
public void setOnLoginListener(Callbacks listener){
this.callbacks = listener;
}
Update #2
where i need to define setOnLoginListener method
Inside the LoginFragment class.
and where should i call it
In your main activity where you first instantiate LoginFragment class.
with what parameters?
Your activity, which implements that Java interface.
You can avoid setting onClickListener for the button by having adding android:onClink="login" in your xml file and a function that looks like this in your java file:
public void login(View view) {
application.getAuth().getUser().setIsLoggedIn(true);
callBacks.onLoggedIn();
}
You can try writing a public setter for the callBacks object in LoginFragment and setting it from the activity instead, like this, supposing you defined your fragment in the activity's layout file:
public class LoginNarrowActivity extends BaseActivity implements LoginFragment.CallBacks {
#Override
protected void onCreate(Bundle savedState){
super.onCreate(savedState);
setContentView(R.layout.activity_login_narrow);
LoginFragment loginFragment = (LoginFragment)getSupportFragmentManager().findFragmentById(R.id.your_fragment_id);
loginFragment.setCallBacks(this);
}
Actually the error was here in onAttach(Context context) when i pass Activity like this onAttach(Activity activity) then it worked. But i want to know why it is causing the error? and onAttach(Activity activity) is deprecated in android 5.0
This question already has answers here:
How can I fix 'android.os.NetworkOnMainThreadException'?
(66 answers)
Closed 7 years ago.
I am getting NetworkOnMainThreadException while running my code. I have a Fragment where i am showing some ID from the webservices that gets called when i click on a button. Following is my code. I have used Asynctask as mentioned for this purpose but still i keep getting this error.
public class AboutMeFragView extends Fragment implements ObsrvIntModel {
private Button getConfButton;
private UsrDataCtrl m_UsrDataCtrl;
private UsrDataModel m_UsrDataModel;
private boolean m_bResUpdate;
private String retc;
public static AboutMeFragView newInstance() {
AboutMeFragView aboutMeFragment = new AboutMeFragView();
return aboutMeFragment;
}
public AboutMeFragView() {}
//inflate the data on this view from the relevant xml file fragment_about_me.xml
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_about_me, container, false);
getConfButton = (Button) rootView.findViewById(R.id.get_config_button);
getConfButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Toast.makeText(getActivity(), "Implement methods to get the configuration", Toast.LENGTH_LONG).show();
//call your model to get the data from the server and show it on the UI
enableStrictMode();
new GetCredsTask().execute();
}
});
return rootView;
}
//whenever fragment is associated with our main activity
//following method would get called
//also we make sure here that whatever navigation activity is selected
//our action bar shows up the same activity name
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
((CpActivity)activity).onSectionAttached(1);
}
#Override
public void update(boolean result) {
m_bResUpdate = result;
}
public void enableStrictMode()
{
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
private class GetCredsTask extends AsyncTask<Void, Void, String> {
public GetCredsTask() {
super();
}
#Override
protected String doInBackground(Void... params) {
m_UsrDataModel = new UsrDataModel(AboutMeFragView.this);
m_UsrDataCtrl = new UsrDataCtrl(m_UsrDataModel);
m_UsrDataCtrl.execConfig();
retc = m_UsrDataModel.getM_authid();
if(m_bResUpdate != true) {
retc = "404";
}
Log.d("doInBackground", retc);
return retc;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String s) {
Log.d("onPostExecute", retc);
if (m_bResUpdate == true)
Toast.makeText(getActivity(), s, Toast.LENGTH_LONG).show();
else
Toast.makeText(getActivity(), retc, Toast.LENGTH_LONG).show();
super.onPostExecute(s);
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
protected void execute() {
doInBackground();
}
}
}
Thanks
You are overriding execute(), which is causing the task to be posted on the main thread instead of executed in the background. The normal implementation posts the execution of the task to a background thread, i.e.
Edit:
public final AsyncTask<Params, Progress, Result> More ...execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
I am using Johan Nilsson Android Pull to Refresh library in my android application. The problem I am having is that the onRefresh method seems to not being called (since none of my logs are displayed) what is causing this and how do I fix it.
public class MyFragment extends RoboFragment implements ResponseListener<List<TimelineItem>>{
#InjectView (R.id.TwitterList) private PullToRefreshListView listView;
private List<TimelineItem> results;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState)
{
return inflater.inflate(R.layout.fragment_timeline, container,false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
listView.setOnRefreshListener(new OnRefreshListener() {
public void onRefresh() {
Log.v("onRefresh", "done");
new FetchNewData().execute("");
}
});
TimelineTask request = new TimelineTask(getActivity());
request.onResponseListener(this);
request.execute(new String());
}
/**
* Callback handler that is called
* after data is fetched from server.
* #author mario
*/
public void onComplete(List<TimelineItem> result)
{
if (result != null && !result.isEmpty())
{
this.results = result;
Collections.sort(results,Collections.reverseOrder());
TimelineAdapter adapter = new TimelineAdapter(getActivity(),R.layout.fragment_timeline_item, results);
listView.setAdapter(adapter);
}
else
Toast.makeText(getActivity(), "No Account! Available Please an Account", Toast.LENGTH_LONG).show();
}//end onComplete method
private class FetchNewData extends AsyncTask<String, Void,List<TimelineItem> >
{
#Override
protected void onPostExecute(List<TimelineItem> result)
{
results.addAll(result);
listView.onRefreshComplete();
Log.v("onPostExecuted", "done");
}
#Override
protected List<TimelineItem> doInBackground(String... params)
{
Log.v("doInBackground", "done");
Collections.sort(results);
return results;
}
}