I'm working with two classes, and model class and a dialog class in android. The model class keeps a list of listeners, which the dialog adds to.
public class SmartChannelModel {
private List<OnResultsChanged> mOnResultsChanged
public interface OnResultsChanged {
void onResultsChanged(int changed);
}
public SmartChannelModel() {
mOnResultsChanged = new List<OnResultsChanged>();
}
public void addResultListener(OnResultsChanged listener) {
mOnResultsChanged.add(listener);
}
}
And my dialog class:
public class InfoDialog extends AppCompatDialog {
private SmartChannelModel model;
public InfoDialog(Context context, SmartChannelModel model) {
super(context);
this.model = model;
}
public void update() {
//do some stuff
}
#Override
protected void onStart() {
super.onStart();
model.addOnResultsChanged(new OnResultsChanged() {
#Override
void onResultsChanged(int changed) {
update();
}
});
}
}
When I create and dismiss this dialog, will garbage collection ever be performed on it since the dialog added a listener to the model class? Do I need to specifically remove any listeners that I've added?
Thank you for the help!
As far as i know Yes if there is no other reference to it anywhere in the class.
Related
I've been trying to find a way to create a listener for a boolean on an android code reader. Essentially what I want to happen is, when it stops reading, perform action. So far I've based it off of this example, and have this:
Class:
public class scanStatusListener {
ScanManager scanManager;
private boolean scanStatus = scanManager.isReading(); //this returns if the reader is scanning or not
private ChangeListener listener;
public void setListener(ChangeListener listener) {
this.listener = listener;
}
public interface ChangeListener {
void onChange();
}
}
Activity:
public class ScanHook extends Service implements ScanManager.DataListener, scanStatusListener.ChangeListener{
private ScanManager _scanManager;
#Override
public void onCreate() {
super.onCreate();
_scanManager = ScanManager.createScanManager(getApplicationContext());
scanStatusListener ss = new scanStatusListener();
ss.setListener(new scanStatusListener.ChangeListener() {
public void onChange() {
//perform action
}
});
}
The issue I am getting is:
private boolean scanStatus = scanManager.isReading();
is getting an error saying that I cannot invoke on a null object reference.
I also tried using the LiveData suggestion:
MutableLiveData<Boolean> listen_bool=new MutableLiveData<>();
listen_bool.observe((LifecycleOwner) this, new Observer<Boolean>() {
#Override
public void onChanged(Boolean aBoolean) {
//perform action
}
});
listen_bool.setValue(_scanManager.isReading());
however I am getting an error saying I cannot cast to androidx.lifecycle.LifecycleOwner
Any suggestions?
I am trying to understand callbacks in Java, but it's confusing me a lot. I know callbacks are passed as an object by implementing interface. But I'm not able to understand how the functions of those passed objects in arguments are invoked.
I took this example
interface ClickEventHandler {
public void handleClick();
}
//Step 2: Create a callback handler
//implementing the above interface
class ClickHandler implements ClickEventHandler {
public void handleClick() {
System.out.println("Clicked");
}
}
//Step 3: Create event generator class
class Button {
public void onClick(ClickEventHandler clickHandler) {
clickHandler.handleClick();
}
}
public class Tester {
public static void main(String[] args) {
Button button = new Button();
ClickHandler clickHandler = new ClickHandler();
//pass the clickHandler to do the default operation
button.onClick(clickHandler);
Button button1 = new Button();
//pass the interface to implement own operation
button1.onClick(new ClickEventHandler() {
#Override
public void handleClick() {
System.out.println("Button Clicked");
}
});
}
}
Output is
```none
Clicked Button
Clicked.
I mean to invoke the function of passed objects we need to register it and call the functions. How does it work in case of listeners? It would be helpful if someone guide me in understanding this.
Well, you'd normally maintain a reference to ClickEventHandler (or even a list if you want to support multiple) and call the method when the button is clicked.
Example:
class Button {
private ClickEventHandler clickHandler;
public void onClick(ClickEventHandler clickHandler) {
this.clickHandler = clickHandler;
}
public void click() {
if( clickHandler != null ) {
clickHandler.handleClick();
}
}
Now when you invoke onClick() the listener is only registered and it will only be executed when the button is clicked (i.e. you call the click() method).
Its easy you just need to create interface
interface HandleClick {
void onItemClick(Boolean success);
}
There's some function to do some work and you need something to return
public static void someFunctions(String params, HandleClick handleClick) {
//some work to do here.
handleClick.onItemClick(true);
}
You can call it anywhere
class Main extends AppCompatActivity {
#Override
public void onCreate(#Nullable Bundle savedInstanceState, #Nullable PersistableBundle persistentState) {
super.onCreate(savedInstanceState, persistentState);
Callbacks.someFunctions("param", new HandleClick() {
#Override
public void onItemClick(Boolean success) {
}
});
}
}
I wrote a simple code to understand how we can do the same callback in 2 different ways.
interface InterestingEvent
{
public void interestingEvent ();
}
public class Test
{
private InterestingEvent ie;
public void EventNotifier (InterestingEvent event)
{
ie = event;
ie.interestingEvent();
}
public static void main(String[] args) {
Test test= new Test();
test.EventNotifier(new InterestingEvent() {
#Override
public void interestingEvent() {
System.out.println("I am callback code");
}
});
}
}
public class Test implements InterestingEvent{
#Override
public void interestingEvent() {
System.out.println("Hello i am callback code");
}
public void EventNotifier ()
{
this.interestingEvent();
}
public static void main(String[] args) {
Test test =new Test();
test.EventNotifier();
}
}
This is for an Android app using Android Studio.
I have a class that listens to, and handles RFID reader events.
This is a separate class the the one associated with the activity. The RFID EPC is being read in the class that handles the RFID events, but I want to display this EPC on the UI, but I am not sure how to achieve this.
I have tried implementing ValueSubmittedListener, but not sure how to bind it all together to make it work:
what I have is
public class ReadMemoryActivity extends Activity implements
View.OnClickListener, ValueSubmittedListener
{
private TextView txtSelection = (TextView) findViewById(R.id.selection);//where EPC is to be displayed
public void onSubmitted(String epc)
{
txtSelection.setText(epc);
}
and then the class for the Events
public class BaseReadAction implements RfidReaderEventListener
{
private List<ValueSubmittedListener> epcListener = new
ArrayList<ValueSubmittedListener>();
public void addListener(ValueSubmittedListener epc)
{
epcListener.clear();
epcListener.add(epc);
}
private void notifyListeners()
{
for(ValueSubmittedListener epc : epcListener)
{
epc.onSubmitted(getSelection());
}
}
public void setSelection(String epc) {
setEPC = epc;
notifyListeners();
}
I see there are quite a few listeners out there. had a look at TextWatcher as well, but at a glance it looks like it watches a TextView more than just a string variable. I'm still quite new to android dev and Java in general so my knowledge falls well short of what fits with what.
Should be EditText instead of TextView, no?
Textwatcher can do a lot:
code:
txtSelection.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable s) {}
#Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
}
});
So this is what I ended up doing to get it to work.
it is an answer, may not be the best answer, certainly not the only answer but here it is...
in the baseClass I added the following
public class BaseReadAction extends Activity implements
RfidReaderEventListener {
private String epcNo;
private ChangeListener listener;
public String getEpcNo()
{
return epcNo;
}
public void setEpcNo(String epc)
{
this.epcNo = epc;
if(listener != null) listener.onChange();
}
public ChangeListener getListener() {
return listener;
}
public void setListener(ChangeListener listener) {
this.listener = listener;
}
public interface ChangeListener
{
void onChange();
}
}
Then in the UI class in the key_Down event that triggers the scanning I put this.
// listens for event when epc is assigned to variable (ReadAction is an instance of BaseReadAction class
ReadAction.setListener(new BaseReadAction.ChangeListener(){
#Override
public void onChange()
{
txtSelection.setText(ReadAction.getEpcNo());//sets the read value to the textView
}
I have a dialog that adds items to a listview, and when an item is added I need to reset the list adapter (because if not things get weird).
I read here that I can create an event listener and listen to it in the main activity. I tried doing so but it gives me errors.
AddMovieDialog.java:
public class AddMovieDialog extends DialogFragment {
private OnFinishListener onFinishListener;
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
builder.setView(inflater.inflate(R.layout.add_movie_dialog, null))
.setTitle("Add a movie")
.setPositiveButton("Add", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// stuff
if (!movieName.isEmpty()) {
// stuff
if (AddMovieDialog.this.onFinishListener != null)
AddMovieDialog.this.onFinisheListener.finish();
}
}
});
// Create the AlertDialog object and return it
return builder.create();
}
public void setOnFinishListener(OnFinishListener listener) {
this.onFinishListener = listener;
}
public interface OnFinishListener {
void finish();
}
}
In the MainActivity:
AddMovieDialog addMovieDialog = new AddMovieDialog();
addMovieDialog.setOnFinishListener(new OnFinishListener() {
public void finish() {
}
});
But it gives me a compilation error: "The method setOnFinishListener(new OnFinishListener(){}) is undefined for the type AddMovieDialog"
You need to call a method which is non-static using the object. You can't call it using just the class name.
Change to this
AddMovieDialog addMovieDialog = new AddMovieDialog();
addMovieDialog .setOnFinishListener(new OnFinishListener() {
public void finish() {
}
});
Also shouldn't
if (AddMovieDialog.this.onCloseListener != null)
AddMovieDialog.this.onCloseListener.finish();
be
if (AddMovieDialog.this.onFinishListener != null)
AddMovieDialog.this.onFinishListener.finish();
EDIT
Seem your import statement in MainActivity is wrong. It should be something like com.yourpackagename.AddMovieDialog.OnFinishListener
I try a Toast Message interface. If app not connection internet, I want show a Toast Message and I'm wanting java interfaces.
This is MotherActivity.java. This file implement ToastMessagges.ToastMessaggeCallback
public class MotherActivity extends ActionBarActivity implements ToastMessagges.ToastMessaggeCallback {
ToastMessagges toastMessagges;
#Override
protected void onStart() {
super.onStart();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mother);
toastMessagges = new ToastMessagges();
AppStarter();
}
private void AppStarter(){
boolean checkinternet = InternetControl.checkInternetConnection( getApplicationContext() );
if( checkinternet ) {
toastMessagges.show_toast_messagge();
}
else {
}
}
#Override
public void LongToastMessagge() {
Toast.makeText(getApplicationContext(), "Hello World", Toast.LENGTH_LONG).show();
}
}
This is my ToastMessagges.java file.
public class ToastMessagges {
ToastMessaggeCallback toastMessaggeCallback;
public void show_toast_messagge(){
toastMessaggeCallback.LongToastMessagge();
}
public static interface ToastMessaggeCallback {
public void LongToastMessagge();
}
}
When the start this app. I get NullPointerException error.
Caused by: java.lang.NullPointerException
at com.medyasef.bulenttirasnewapp.bulenttiras.functions.ToastMessagges.show_toast_messagge(ToastMessagges.java:22)
at com.medyasef.bulenttirasnewapp.bulenttiras.MotherActivity.AppStarter(MotherActivity.java:36)
at com.medyasef.bulenttirasnewapp.bulenttiras.MotherActivity.onCreate(MotherActivity.java:29)
ToastMessagges.java:22
toastMessaggeCallback.LongToastMessagge();
Sorry bad english.
Please help.
Thank you.
You haven't initialized you ToastMessaggeCallback toastMessaggeCallback.
To do this, write
ToastMessaggeCallback toastMessaggeCallback = new ToastMessaggeCallback(){
public void LongToastMessagge(){
// add some toasting code here
}
};
This will make an object implementing your interface (called "anonymous class"). Of course, your ToastMessaggeCallback should do something in the method LongToastMessagge, so add the desired code there.
I will recommend you to create a Util class instead of Interface. I'm here giving you an example of Util class.
public class Util {
public static void showToast(Context context, String text) {
Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
}
}
Then call the showToast() method from your activity as follows...
Util.showToast(YourActivity.this, "text");
Update:
Declare your Interface as a individual, not inside a class as below...
public interface ToastMessaggeCallback {
public void showLongToastMessagge(String text);
}
Then implement the Interface as follows...
public class MotherActivity extends ActionBarActivity implements ToastMessaggeCallback {
#Override
protected void onStart() {
super.onStart();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mother);
AppStarter();
}
private void AppStarter(){
boolean checkinternet = InternetControl.checkInternetConnection( getApplicationContext() );
if( checkinternet ) {
showLongToastMessagge("Hello World");
}
else {
}
}
#Override
public void showLongToastMessagge(String text) {
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_LONG).show();
}
}
Your ToastMessagges class needs to provide a method to register the callback. Then, your Activity needs to call this method to register itself as the callback, right after you construct the ToastMessages object.