I would like to sort my DefaultListModel and have it to fire the contents changed event, but I'm stuck with it, and don't understand how can I call its fireContentsChanged method. I see that if my model extends AbstractListModel I can directly call the fireContentsChanged after the sorting, but in the way I did my class with the DefaultListModel, I can't call its fireContentsChanged cause it has protected access. Do I have to extends AbstractListModel
or is there a way to call the DefaultListModel fireContentsChanged ?
public class DefaultDataModel implements DataModel
{
private DefaultListModel<Data> dataModel = new DefaultListModel<>();
#Override
public void addElement(Data data) {
dataModel.addElement(data);
}
#Override
public int getSize() {
return dataModel.getSize();
}
#Override
public Data getElementAt(int idx) {
return dataModel.getElementAt(idx);
}
#Override
public void addListDataListener(ListDataListener l) {
dataModel.addListDataListener(l);
}
#Override
public int indexOf(Data data) {
return dataModel.indexOf(data);
}
#Override
public List<Data> getAllData() {
return Collections.list(dataModel.elements());
}
#Override
public void sort() {
Collections.sort(getAllData());
}
}
I found how to do it in the sort method I have to call the contentsChanged method from the dataModel listeners list.
#Override
public void sort() {
Collections.sort(getAllData());
ListDataListener[] listeners = dataModel.getListDataListeners();
for(ListDataListener listener : listener) {
listener.contentsChanged(dataModel, ListDataEvent.CONTENTS_CHANGED, 0, getSize());
}
}
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();
}
}
How to read/write java.math.BigInteger properly when implementing Parcelable interface in Android?
I would recommend writing in BigInteger as a String.
public class MyParcelable implements Parcelable {
public static final Creator<MyParcelable> CREATOR = new Creator<MyParcelable>() {
#Override
public MyParcelable createFromParcel(Parcel in) {
return new MyParcelable(in);
}
#Override
public MyParcelable[] newArray(int size) {
return new MyParcelable[size];
}
};
private BigInteger mData;
protected MyParcelable(Parcel in) {
mData = new BigInteger(in.readString());
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(mData.toString());
}
}
I created this extension of ArrayList, NullIgnoringArrayList, because it's possible that my application will add nulls from time to time. I know there are various other ways to deal with this, like checking for null before inserting or filtering out nulls when accessing the ArrayList. But I got it in my head to do it this way and it was going fine but now I don't know how to proceed.
I should implement ListIterator because my tests call upon this method. I peaked in the implementation inside ArrayList but there ListItr is a private class that uses the private fields of ArrayList, which I don't have in NullIgnoringArrayList.
To be fair though, I might be overengineering and maybe I should just drop it. On the other hand, one might learn a thing or two.
NullIgnoringArrayList:
public class NullIgnoringArrayList<T> extends ArrayList<T> {
#Override
public boolean add(T element) {
return !isNull(element) && super.add(element);
}
#Override
public void add(int index, T element) {
if (isNull(element)) {
return;
}
super.add(index, element);
}
#Override
public boolean addAll(Collection c) {
return !isNull(c) && super.addAll(c);
}
#Override
public boolean addAll(int index, Collection c) {
return !isNull(c) && super.addAll(index, c);
}
#Override
public ListIterator listIterator() {
throw new NotImplementedException();
}
#Override
public ListIterator listIterator(int index) {
throw new NotImplementedException();
}
}
SimpleListIterator:
public class SimpleListIterator<T> implements ListIterator {
#Override
public boolean hasNext() {
return false;
}
#Override
public Object next() {
return null;
}
#Override
public boolean hasPrevious() {
return false;
}
#Override
public Object previous() {
return null;
}
#Override
public int nextIndex() {
return 0;
}
#Override
public int previousIndex() {
return 0;
}
#Override
public void remove() {
}
#Override
public void set(Object o) {
}
#Override
public void add(Object o) {
}
}
Just delegate method calls to ListIterator<T> of the parent:
public class NullIgnoringArrayList<T> extends ArrayList<T> {
...
#Override
public ListIterator<T> listIterator() {
return new SimpleListIterator<>(super.listIterator());
}
#Override
public ListIterator<T> listIterator(int index) {
return new SimpleListIterator<>(super.listIterator(index));
}
}
public class SimpleListIterator<T> implements ListIterator<T> {
private final ListIterator<T> underlying;
public SimpleListIterator(ListIterator<T> underlying) {
this.underlying = underlying;
}
#Override public boolean hasNext() {return underlying.hasNext();}
#Override public T next() { return underlying.next(); }
#Override public boolean hasPrevious() {return underlying.hasPrevious();}
#Override public T previous() {return underlying.previous();}
#Override public int nextIndex() {return underlying.nextIndex();}
#Override public int previousIndex() {return underlying.previousIndex();}
#Override public void remove() { underlying.remove();}
#Override
public void set(T o) {
if (isNull(o)) {return;}
underlying.set(o);
}
#Override
public void add(T o) {
if (isNull(o)) {return;}
underlying.add(o);
}
}
public interface DownloadListener {
public void onDownloaded();
}
public class DownloadManager {
private static DownloadManager instance;
private DownloadListener mDownloadListener;
public static synchronized DownloadManager getInstance(){
if(instance == null)
instance = new DownloadManager();
return instance;
}
private DownloadManager() {
myHandler.sendEmptyMessageDelayed(29, 3 * 1000);
}
public void registerDownloadListener(DownloadListener downloadListener) {
mDownloadListener = downloadListener;
}
Handler myHandler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
if (msg.what == 29) {
mDownloadListener.onDownloaded();
return true;
}
return false;
}
});
}
public class I implements DownloadListener {
public I() {
DownloadManager.getInstance().registerDownloadListener(this);
}
#Override
public void onDownloaded() {
Log.e("TAG", "I onDownloaded");
}
}
public class You implements DownloadListener {
public You() {
DownloadManager.getInstance().registerDownloadListener(this);
}
#Override
public void onDownloaded() {
Log.e("TAG", "You onDownloaded");
}
}
public class PATTERNSActivity extends Activity implements DownloadListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new I();
new You();
DownloadManager.getInstance().registerDownloadListener(this);
}
#Override
public void onDownloaded() {
Log.e("TAG","PATTERNSActivity onDownloaded");
}
}
I am expecting to get:
I onDownloaded
You onDownloaded
PATTERNSActivity onDownloaded
But I am getting only:
PATTERNSActivity onDownloaded
What could it be the problem?
You keep registered downloaders in a single instance property:
// Last call's downloadListener wins.
public void registerDownloadListener(DownloadListener downloadListener) {
mDownloadListener = downloadListener;
}
The last one registered is the activity's:
new I(); // First set singleton's property to an instance of I...
new You(); // ...then to an instance of You...
// ...then to the current instance.
DownloadManager.getInstance().registerDownloadListener(this);
Edit based on your comment.
public void registerDownloadListener(DownloadListener downloadListener) {
mDownloadListeners.add(downloadListener);
}
...
public boolean handleMessage(Message msg) {
if (msg.what != 29) {
return false;
}
for (DownloadListener listener : mDownloadListeners) {
listener.onDownloaded();
}
return true;
}
In your code, this gets executed by calling mDownloadListener.onDownloaded(); in the DownloadManager class.
#Override
public void onDownloaded() {
Log.e("TAG","PATTERNSActivity onDownloaded");
}
In don't see why the onDownloaded methods of the I and YOU class should be executed, they're never called. Only the OnDownloaded method of your Listener is called.
For starters, I think you are not using a list. You just override the value so you will always get the last one:
public void registerDownloadListener(DownloadListener downloadListener) {
mDownloadListener = downloadListener;
}