In my android application inside activity I am defining one interface like this :
public interface sideFilterInterface
{
public void changeFilters(int layoutId);
}
inside activity I use this interface like this
#Override
public void onCreate(Bundle savedInstanceState) {
mCallback = (sideFilterInterface) this;
mCallback.changeFilters(R.layout.filter_details);
}
I am implementing this interface in another fragment. when i tried this code it gives me error regarding casting here mCallback = (sideFilterInterface) this;
How to do this. Am I doing something wrong. Need help. Thank you.
The main thing is you are trying to cast your Activity into Listener if you are not implementing the Listener in your activity.
If you are calling the public void changeFilters(int layoutId) through the interface , the code will not execute as the method in the interface is abstract.You need to implement the listener in the activity and then do the code there . Something like :
public class YourActivity extends Activity implements sideFilterInterface{
#Override
public void onCreate(Bundle savedInstanceState) {
//some code
this.changeFilters(R.layout.filter_details);
}
#Override
public void changeFilters(int layoutId) {
//Implement here
}
}
Related
I have not found a clear solution anywhere on stack for this.
Here's my basic set up
public class Activity1 extends AppCompatActivity
{
private OnAttributesUpdatedListener onAttributesUpdatedListener;
public interface OnAttributesUpdatedListener
{
public void onAttributesUpdated();
}
public void setTargetFragment(Fragment fragment)
{
this.onAttributesUpdatedListener = (OnAttributesUpdatedListener) fragment;
}
private void whenFinishedSomethingCallback()
{
onAttributesUpdatedListener.onAttributesUpdated();
}
}
public class Fragment1 extends Fragment implements Activity1.OnAttributesUpdatedListener
{
button.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view) {
if(rivalButtonClick == 0)
{
Activity1 activity1 = new Activity1();
activity1.setTargetFragment(Fragment1.this);
startActivity(new Intent(getActivity(), activity1.getClass()));
}
}
});
}
I get a null pointer exception and crashes on : onAttributesUpdatedListener.onAttributesUpdated(); because for some reason my listener never gets set properly. What's the proper way to do this?
You need to set the listener at start of the fragment onCreatView() or in onActivityCreated() only if the Desired Activity is a parent Activity of that particular fragment. Below is an example .
public class Activity1 extends AppCompatActivity {
private OnAttributesUpdatedListener onAttributesUpdatedListener;
public interface OnAttributesUpdatedListener {
public void onAttributesUpdated();
}
public void setListener(OnAttributesUpdatedListener onAttributesUpdatedListener) {
this.onAttributesUpdatedListener = onAttributesUpdatedListener;
}
private void whenFinishedSomethingCallback() {
if(onAttributesUpdatedListener!=null)
onAttributesUpdatedListener.onAttributesUpdated();
}
}
public class Fragment1 extends Fragment implements Activity1.OnAttributesUpdatedListener
{
#Override
public void onAttributesUpdated() {
// Do your stuff here
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
((Activity1)getActivity()).setListener(this);
}
}
Read about fragment Life cycle to make use of getActivity(). also remove the listener when fragment is destroyed .
Use LocalBroadcastManager for communicating between in case the Fragment exists in other Activity.
At first create an Interface like this:
public interface Listener{
void doSomething() }
Then implement this interface in your activity.
And also add
Listener listener
In your fragment
And in onAttach method in fragment use this
listener=(Listener)activity
Then call listener whenever you need .
I decided to try and make my code more object oriented and avoid repetitive code in another class.
Source code for Activities :
public class EasyMode extends MainActivity {
GameActivityPVP game = new GameActivityPVP();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game_layout_pvp);
game.initializeButtons();
}
}
public class GameActivityPVP extends MainActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game_layout_pvp);
initializeButtons();
}
public void initializeButtons() {
button[0] = (Button) findViewById(R.id.button1);
}
}
The second the program gets to the line where I try to call a method using game.methodName(); the program crashes. No compiling errors or anything.
I am new to programming in general so please take it easy on me and I tried to simplify my code as much as possible.
Android Monitor/logcat :
W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
and
W/art: Before Android 4.1, method int android.support.v7.widget.ListViewCompat.lookForSelectablePosition(int, boolean) would have incorrectly overridden the package-private method in android.widget.ListView
You can use another class's method by creating object of parent class.
See below example;
Here you want to use method from 'GameActivityPVP' class. So you need to create one object in this class only.
public class GameActivityPVP extends MainActivity {
public static GameActivityPVP mGameActivity;
public GameActivityPVP getInstance(){
return mGameActivity; // assign value in onCreate() method.
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game_layout_pvp);
mGameActivity = this; // Do not forget this, otherwise you'll get Exception here.
initializeButtons();
}
public void initializeButtons() {
button[0] = (Button) findViewById(R.id.button1);
}
}
Now use this Object in another class 'EasyMode' like this;
if(GameActivityPVP.getInstance()!=null){
GameActivityPVP.getInstance().initializeButtons();
}
Try This:
Make one Class Utils:
In Utils:
public class Utils{
private Activity context;
Button button;
public Utils(Activity context) {
this.context=context;
}
public void inititializeButton(Activity context){
button[0]= (Button) context.findViewById(R.id.button_flasher);
}
}
And in your Class use:
public class EasyMode extends MainActivity {
Utils utils;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game_layout_pvp);
utils=new Utils(this);
utils.initializeButtons();
}
}
As already stated, you shouldn't use nested activities, they are not supposed to interact like this. If you want two activities to interact you have to do it through an intent. Regarding the duplicated code, you have few solution presented but my personal opinion is that the OOP rules are not followed. If I had to write that logic, I would create a BaseActivity to hold the common logic of the other two activities and use inheritance to extend them.
public class BaseActivity extends Activity {
protected List<Button> buttons = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game_layout_pvp);
initializeButtons();
}
protected void initializeButtons() {
buttons.add((Button) findViewById(R.id.button1));
}
}
public class EasyMode extends BaseActivity {
// Add here logic that is used only in EasyMode activity
}
public class GameActivityPVP extends BaseActivity {
// Add here logic that is used only in GameActivityPVP activity
}
Note that in this way you don't have to override onCreate again to initialise the buttons and so on. Also, I saw that you used the same layout for both activities, but if you want to use different layouts you can do it as usual and then call initializeButtons.
I have this issue of sending some data back and forth between a fragment and its container activity, I succeeded in doing it. What puzzles me is sending my data from the fragment to the activity, at first I implemented OnResume(), OnStop() and sent the data through an intent and that created an infinite loop so I removed them. Then I did setRetainInstance(true) and it worked and gave me the wanted behavior.
My Question is How my data are really being sent and where in the fragment lifecycle ?
The Right approach is to use Interfaces. Don't use onStop or setRetainInstance()
See this. It will solve you problem.
Pass data from fragment to actvity
You can also achieve this by using Interface, using an EventBus like LocalBroadcastManager, or starting a new Activity with an Intent and some form of flag passed into its extras Bundle or something else.
Here is an example about using Interface:
1. Add function sendDataToActivity() into the interface (EventListener).
//EventListener.java
public interface EventListener {
public void sendDataToActivity(String data);
}
2. Implement this functions in your MainActivity.
// MainActivity.java
public class MainActivity extends AppCompatActivity implements EventListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void sendDataToActivity(String data) {
Log.i("MainActivity", "sendDataToActivity: " + data);
}
}
3. Create the listener in MyFragment and attach it to the Activity.
4. Finally, call function using listener.sendDataToActivity("Hello World!").
// MyFragment.java
public class MyFragment extends Fragment {
private EventListener listener;
#Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
if(activity instanceof EventListener) {
listener = (EventListener)activity;
} else {
// Throw an error!
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my, container, false);
// Send data
listener.sendDataToActivity("Hello World!");
return view;
}
#Override
public void onDetach() {
super.onDetach();
listener = null;
}
}
Hope this will help~
My Activity has multiple lists so I have defined MyClickListener as below:
My question is how I should instantiate this class:
MyClickListener mMyClickListener = new MyClickListener();
Or maybe it is better to instantiate inside the onCreate(Bundle) and just define above. Whats considered the better way? I don't want too much in onCreate() its already full of stuff. Any thoughts on the declaration and instatiation? Whats the best way?
private class MyClickListener implements OnClickListener
{
#Override
public void onClick(View view) {
}
}
I use same kind of class mechanism as you mentioned in the question.
this is the way i use,
public class myActivity extends Activity
{
private MyListener listener = null;
private Button cmdButton = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
cmdButton = (Button) findViewById(R.id.cmdButton);
cmdButton.setOnClickListener(getListener());
}
// method to fetch the listener object
private MyListener getListener()
{
if (listener == null)
{
listener = new MyListener();
}
return listener;
}
private class MyListener implements Button.OnClickListener
{
public void onClick(View v)
{
}
}
}
Why are you instantiating a listener like that in the first place? Just create a new one when you assign it to your listView.
listView.setOnClickListener( new MyListener());
I have an activity that roughly follows this structure:
public class myActivity extends Activity implements myCallback{
//Code
#Override
public void onCreate(Bundle savedInstaceState){
super.onCreate(savedInstanceState);
new myAsyncTask(myActivity.this).execute();
}
public void myCallback(Context context){
//Code
Toast.makeText(context,"Hello",Toast.LENGTH_SHORT).show();
}
}
And myAsyncTask has the myCallback() interface defined and it calls it eventually. No matter what I do, whatever UI element I try to show, be it a Toast or a ProgressDialog, it won't show. Nor do I get any exceptions. The rest of the callback code gets perfectly executed. Why is this?
Try using:
public class myActivity extends Activity implements myCallback{
//Code
Context mContext;
#Override
public void onCreate(Bundle savedInstaceState){
super.onCreate(savedInstanceState);
mContext = this;
new myAsyncTask(getApplicationContext()).execute();
}
public void myCallback(Context context){
//Code
Toast.makeText(mContext,"Hello",Toast.LENGTH_SHORT).show();
}
}
Instead of using context , use getApplicationContext... i hope it will show toast... like this
Toast.makeText(getApplicationContext(),"Hello",Toast.LENGTH_SHORT).show();