I have a method inside MainActivity named PlaySong(), and from MainActivity, I'm calling a custom AlertDialog class like this
SongListDialog songlistDialog = new SongListDialog(this, songsList);
songlistDialog.show();
how can I call PlaySong() from songlist which is inside the SonglistDialog. Currently I have this ListView and I can track the click on any song using the following code:
#OnClick(R.id.card_view)
void onClick() {
Song song = songs.get(getAdapterPosition());
dialog.dismiss();
// here I want to call PlaySong() method which is inside MainActivity
}
Any idea how to do this?
the best way to avoid leaks is to create a listener interface
public interface SongListListener {
void playSong(Song song);
}
then on your SongListDialog constructor
private final SongListListener mListener;
public SongListDialog(SongListListener listener, ...) {
mListener = listener;
}
#OnClick(R.id.card_view)
void onClick() {
Song song = songs.get(getAdapterPosition());
dialog.dismiss();
// notify listener
mListener.PlaySong(song);
}
Finally implements SongListListener in your MainActivity
public class MainActivity extends Activity implements SongListListener {
//...
#Override
void playSong(Song song){
//do whatever you want with the song here
}
//...
}
You can use a callback.
public interface OnSongSelectedListener{
void onSongSelected(Song song);
}
// Then in your Activity
SongListDialog songlistDialog = new SongListDialog(this, songsList, songSelectedListener);
songlistDialog.show();
Ideally, the Activity itself should implement the interface. So songSelectedListener will be MainActivity.this.
Then in the onClick you do:
void onClick() {
Song song = songs.get(getAdapterPosition());
listener.onSongSelected(song); // Return the selected song
dialog.dismiss();
// here I want to call PlaySong() method which is inside MainActivity
}
Since you are passing the MainActivity in new SongListDialog(this, songsList) you can directly call playSong on it by casting e.g.
public SongListDialog(Context ctx, ...) {
((MainActivity) ctx).playSong();
}
you want to pass context in adapter from your activity and use that context
((MainActivity)context).playSong();
Related
I have created an volley list in this i have problem to get data from adapter to activity and this activity to another activity. I have received error cannot cast activity.java to anotherActivity.java below is my code. Please help me anyone thanks.
My Interface itemclick in Adapter class
private OnItemClickGetPlaylist mListener;
public interface OnItemClickGetPlaylist{
public void OnPlaylistItemClick(String playlistName,int numOfItems,String imageViewForPlaylist);
}
public void setOnClickListenerOnPlaylist(OnItemClickGetPlaylist listener)
{
mListener = listener;
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String id = playlist.getId_playlist_identify();
String PlaylistName = playlist.getTitile_of_playlist();
String imageOfPlaylist = playlist.getImage_of_playlist();
int numOfPlaylistSongs = getItemCount();
SendIdToDatabase(id);
if (mListener != null)
{
mListener.OnPlaylistItemClick(PlaylistName,numOfPlaylistSongs,imageOfPlaylist);
}
else {
Toast.makeText(context, "mListeren is null" + mListener, Toast.LENGTH_SHORT).show();
}
}
});
After get data handle OnPlaylistItemClick click in Activity below Codes
public void OnItemClickHandleInPlaylistActivity(String playlistName,int numOfItems,String imageViewForPlaylist)
{
//here is the adapter item click in activity now i want to send that data to another activity without any intent please help me.
// i have implement below code but it give me cannot cast activity to another activity error.
((anotherActivity) getApplicationContext()).OnItemClickInMusicActivity(playlistName,numOfItems,imageViewForPlaylist);
}
See the solution at https://stackoverflow.com/a/47637313/2413303
public class MyApplication extends Application {
private static MyApplication INSTANCE;
DataRepository dataRepository; // this is YOUR class
#Override
public void onCreate() {
super.onCreate();
INSTANCE = this;
dataRepository = new DataRepository();
}
public static MyApplication get() {
return INSTANCE;
}
}
The DataRepository should expose LiveData:
public class DataRepository {
private final MutableLiveData<MyData> data = new MutableLiveData<>();
public LiveData<MyData> getMyData() {
return data;
}
public void updateText(String text) {
MyData newData = data.getValue()
.toBuilder() // immutable new copy
.setText(text)
.build();
data.setValue(newData);
}
}
Where the Activity subscribes to this:
public class MyActivity extends AppCompatActivity {
DataRepository dataRepository;
TextView textView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyApplication app = (MyApplication)getApplicationContext();
dataRepository = app.getDataRepository();
setContentView(R.layout.main_activity);
textView = findViewById(R.id.textview);
dataRepository.getMyData().observe(this, new Observer() {
#Override
public void onChange(MyObject myObject) {
textView.setText(myObject.getText());
}
}
}
So to update this text, you need to get the DataRepository class, and call updateText on it:
DataRepository dataRepository = MyApplication.get().dataRepository();
dataRepository.updateText("my new text");
Make sure that the data in DataRepository is properly persisted somewhere, or at least can be obtained again after process death. You might want to use a database for example (but not shared preferences).
If you don't want to use Intents, maybe you can use a publish/subscribe architecture. There is a library called eventbus (org.greenrobot:eventbus) very easy to use which could achieve what you want.
Use an Application Class instead.
public class MyApplicationClass extends Application{
#Override
public void onCreate() {
super.onCreate();
///do something on create
}
getterMethods(){...}
setterMethods(){...}
}
then add android:name=".MyApplicationClass" to manifest file
Now you can access the methods in class by
MyApplicationClass applicationClass = (MyApplicationClass)getApplicationContext();
int id = applicationClass .getterMethod().getID;
String playListName = applicationClass .getterMethod().getPlayListName();
and vice versa for Setter();
after that you can use it for data getting and setting Data throughout the application.
Hope it helps :)
References:
https://guides.codepath.com/android/Understanding-the-Android-Application-Class
I find the best to use callbacks.
in ClassA:
Create interface
MyCallback callback;
viod setCallback(MyCallback callback){
this.callback = callback;
}
viod onStop(){
callback = null;
}
interface MyCallback{
void doSomething(Params params);
}
in ClassB:
implement MyCallback
public class ClassB **implements ClassA.MyCallback**
set reference in onCreate
ClassA classA = new ClassA();
classA.setCallback(this);
// override method doSomething
#override
void doSomething(Params params){
//do your thing with the params…
}
when the job is done inside class A call:
callback.doSomething(params);
destroy reference inside class B in onStop()
classA.onStop();
I need to pass an OnClickListener object from activity to a Fragment.
I can't pass argument to Fragment constructor, so i want to do something like:
Bundle bundle = new Bundle();
bundle.putCustomObject(new OnClickListener(){...});
I think the best approach is to create an interface with a method onClick() and set the callback from the Activity to the Fragment.
Interface
public interface FragmentClickListener
{
void onClick();
}
Create a variable and method in Fragment class to receive the FragmentClickListener:
private FragmentClickListener listener;
public void setOnClickListener(FragmentClickListener listener)
{
this.listener = listener;
}
Then in some method of your Fragment class you can call the listener like this:
void someMethod()
{
if(listener != null) {
listener.onClick();
}
}
In your Activity class define the call back like this:
fragment.setOnClickListener(new FragmentClickListener(){
#Override
public void onClick() {
//do something here
}
});
Add a method to the fragment:
public void setOnClickListener(OnClickListener listener) { mListener = listener;}
Call Fragment's method:
mFragment.setOnClickListener(new OnClickListener() { /* YOUR CODE HERE */ });
I created a very simple listener interface that looks like this:
public interface ReportDialogListener {
void shouldRemoveBlockedUser();
}
Now, in my ReportDialog class which is defined like this:
public class ReportDialog extends Dialog implements View.OnClickListener {}
I want to implement this listener and send callback for a certain action. However, when I do send callback after a certain action... my mDialogListener variable is null.
Where do I set the context?
This is what I tried:
private ReportDialogListener mDialogListener;
#Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
try {
mDialogListener = (ReportDialogListener) getContext();
} catch (ClassCastException e) {
}
}
#Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
mDialogListener = null;
}
But when I call mDialogListener.shouldRemoveBlockedUser();, mDialogListener is null...
Also- I made sure my main activity was implementing ReportDialogListener... thanks
Implement Listener in MainActivity
Public class MainActivity implements ReportDialogListener {
ReportDialogListener reportDialogListener ;
public void onCreate(Bundle saveInstanceState){
reportDialogListener =this;
}
#override
public void shouldRemoveBlockedUser(){
}
}
Pass reportDialogListener object to other class or activity and call the listener method reportDialogListener.shouldRemoveBlockedUser();
If this main activity implements the interface, do not use the activity context. Use this instead. mDialogListener = this;
Also i do not see where you implement the interface,only the View onClick interface you have actually implemented.
public class ReportDialog extends Dialog implements View.OnClickListener
to
public class ReportDialog extends Dialog implements View.OnClickListener,ReportDialogListener
To implement the interface in another, either you define it in the constructor of the calling program, or devise a method that does it.
Since my main activity was actually sending this when creating an instance of ReportDialog :
if (mReportDialog == null) {
mReportDialog = new ReportDialog(this);
}
I was able to assign it to a variable in the constructor of ReportDialog
public ReportDialog(Activity activity) {
super(activity);
mActivity = activity;
init();
}
Then, use it like this:
mDialogListener = (ReportDialogListener) mActivity;
Works perfectly.
I have searched SO for this problem but was not able to find anything which would solve my problem. My problem is, I have a activity which contains FrameLayout which is constantly updated with different fragments. The top view and bottom view are going to remain same hence they are in the layout of the
activity.
As you can see bottom view has a button on click of that i want to make changes in the fragments which will be present in the FrameLayout.
I have created a interface
public interface ShowFormula {
void showFormula(boolean show);
}
which i will use to implement in the fragment.
Now the main problem in my MainActivity class i am trying to initialize the interface but not able to as i am getting class cast exception
showFormula = (ShowFormula) this;//yes i know this is wrong
How should i initialize this in order to communicate with the fragment.
Main goal is to toggle the view in fragments on click of the button in activity.
Thanks in advance.
You don't need to use an interface to make calls from an Activity to a Fragment. Just keep a reference to the current Fragment, and call into a public method in the Fragment from the Activity.
If you have multiple Fragments and you don't want to keep a reference for each one, you can create a Fragment base class, declare the common method in the base class, and then implement that method override in all of your Fragments that inherit from the base Fragment. Then, keep one reference of the base Fragment type, and always have it set to the Fragment that is shown currently.
Activity ---> Fragment
Communication from Activity to Fragment is pretty straightforward. You
really don't need a listener.
Let's say you have a method inside Fragment share()
public class MyFragment extends Fragment{
public static MyFragment getInstance()
{
return new MyFragment();
}
........
public void share()
{
// do something
}
}
How to call share() method from an Activity?
Get the reference of the Fragment and call the method. Simple!
MyFragment myFragment = MyFragment.getInstance();
myFragment.share();
You can see the full working code for Fragment to Fragment Communication
Just to add to Daniel Nugent's brilliant answer, here are snippets from my working code for delegating calls from Activity to Fragment.
I have a MVP architecture and I have defined the error handling method showError on the BaseView class and the code below demonstrates how to handle the UI on a TargetFragment class. I, specifically needed to hide my progress spinner on the fragment upon any error scenario. Here's the code snippets for the base classes:
public interface BaseView {
void showError(ErrorResponse errorResponse);
}
public abstract class BaseActivity implements BaseView {
#Override
public void showError(ErrorResponse errorResponse) {
// Check error condition or whatever
// ...
MaterialDialog dialog = new MaterialDialog.Builder(this)
.title(R.string.dialog_error_title)
.content(R.string.error_no_internet)
.positiveText(R.string.dialog_action_ok)
.build();
dialog.show();
}
}
public abstract class BaseFragment implements BaseView {
#Override
public void showError(ErrorResponse errorResponse) {
((BaseView) getActivity()).showError(errorResponse);
}
}
And, this is how I handle UI inside my TargetFragment class:
public final class TargetFragment extends BaseFragment implements TargetView {
#Override
public void showError(ErrorResponse errorResponse) {
super.showError(errorResponse);
hideSpinner();
// Do other UI stuff
// ...
}
private void hideSpinner() {
spinner.setVisibility(View.INVISIBLE);
}
}
a clean solution:
public interface ShowFormula {
public void showFormula(boolean show);
}
public class MyActivity implements ShowFormula {
...
#Override
public void showFormula(boolean show) {
/** Your Code **/
}
...
}
public class MyFragment {
private ShowFormula listener;
...
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
listener = (ShowFormula) activity;
// listener.showFormula(show?);
} catch (ClassCastException castException) {
/** The activity does not implement the listener. **/
}
}
...
}
simple thing make public method in fragments then call it on from your activity.
e.g
MyFragment fragment = new MyFragment();
fragment.doSomeThing();
doSomeThing() is a public method in MyFragment.
Activity to Fragment Communication via Interface:
public class MyActivity {
private ShowFormula showFormulaListener;
public interface ShowFormula {
public void showFormula(boolean show);
}
public void setListener(MyFragment myFragment) {
try {
showFormulaListener = myFragment;
} catch(ClassCastException e) {
}
}
}
public class MyFragment implements ShowFormula{
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
((MyActivity) activity).setListener(this);
} catch (ClassCastException e) {
Log.e(TAG, e.toString());
}
}
#Override
public void showFormula(boolean show) {
/** Your Code **/
}
}
Once you are done setting this, you can call 'showFormulaListener.showFormula(boolVal)'
I am struggling to figure out how to simply call and run a method from a class (that is not an activity) on my current activity.
my current code:
CustomListViewAdapter.java (other class)
public void onClick(View v) {
int position = Photos.listView.getPositionForView(v);
Log.v("value ", "tada" + position);
Photos photos = new Photos();
photos.deletePhoto(position);
}
});
Photos.java (my current activity class)
public void deletePhoto(int pos){
Toast.makeText(thisActivity, "delete index:"+pos , Toast.LENGTH_SHORT).show();
mylist.remove(pos);
setupListView();
}
Problem is, this way of doing it makes a new instance of mylist which gives me a outofbounds error. How can I do this correctly so I get the current activity and update it accordingly?
If you don't want a static method, you could create in interface.
public interface DeleteInterface {
public void deletePhoto(int position);
}
And then in your adapter's constructor...
private DeleteInterface mInterface;
public CustomListAdapter(/* other paramaters */ DeleteInterface interface) {
// other assignments
mInterface = interface;
}
And then in your Activity...
public class Photos extends Activity implements DeleteInterface {
// your code here
public void deletePhoto(int pos) {
// your method here
}
}
But make sure that when you create your Adapter, you have a pointer to the current Activity and pass it through the Adapter's constructor.
Last but not least...
In your adapter, call mInterface.deletePhoto(position); to call your Activity's method.