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());
}
}
Related
there are many sensors(gps/temperature/brightness) listened by SensorManager.
class Sensor{
public Sensor getInstance(){
}
public register(int id,Listener listener){
}
public unRegister(Listener listener){
}
public interface Listener{
void onDataChange(int id, int value);
}
}
I want to use different widgets to display different sensors.
like this:
abstract class View1 extends TextView{
abstract int getSensorId();
abstract void onValueChange(int value);
public void onAttachToWindow(){
Sensor.getInstance.register(id,listener);
}
public void onDetachFromWindow() {
Sensor.getInstance.unRegister(listener);
}
listener = new Listener(){
void onDataChange(int id, int value){
onValueChange(value);
}
}
}
abstract class View2 extends Button{
abstract int getSensorId();
abstract void onValueChange(int value);
public void onAttachToWindow(){
Sensor.getInstance.register(id,listener);
}
public void onDetachFromWindow() {
Sensor.getInstance.unRegister(listener);
}
listener = new Listener(){
void onDataChange(int id, int value){
onValueChange(value);
}
}
}
abstract class View3 extends ImageView{
abstract int getSensorId();
abstract void onValueChange(int value);
public void onAttachToWindow(){
Sensor.getInstance.register(id,listener);
}
public void onDetachFromWindow() {
Sensor.getInstance.unRegister(listener);
}
listener = new Listener(){
void onDataChange(int id, int value){
onValueChange(value);
}
}
}
abstract class View4 extends LinearLayout {
abstract int getSensorId();
abstract void onValueChange(int value);
public void onAttachToWindow(){
Sensor.getInstance.register(id,listener);
}
public void onDetachFromWindow() {
Sensor.getInstance.unRegister(listener);
}
listener = new Listener(){
void onDataChange(int id, int value){
onValueChange(value);
}
}
}
abstract class View5 extends RelativeLayout{
abstract int getSensorId();
abstract void onValueChange(int value);
public void onAttachToWindow(){
Sensor.getInstance.register(id,listener);
}
public void onDetachFromWindow() {
Sensor.getInstance.unRegister(listener);
}
listener = new Listener(){
void onDataChange(int id, int value){
onValueChange(value);
}
}
}
The problem is too many widget.
I figured out a solvent.(which failed to compile)
abstract AbsView<T extends View> extends T{
abstract int getSensorId();
abstract void onValueChange(int value);
public void onAttachToWindow(){
Sensor.getInstance.register(id,listener);
}
public void onDetachFromWindow() {
Sensor.getInstance.unRegister(listener);
}
listener = new Listener(){
void onDataChange(int id, int value){
onValueChange(value);
}
}
}
expecting i can use it like this
class View1 extends AbsView<TextView>{
int getSensorId(){
return gpsId;
}
void onValueChange(int value){
setText("xxxx");
}
}
class View2 extends AbsView<ImageView>{
int getSensorId(){
return gpsId;
}
void onValueChange(int value){
setImage(xxx);
}
}
class View3 extends AbsView<LinearLayout>{
int getSensorId(){
return gpsId;
}
void onValueChange(int value){
addView(xxx);
}
}
Them the compiler told me I can't do this.
So,is there any more elegant ways to accomplish it?
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);
}
}
I am trying to use the Android ez vcard library to create vcf file from my object. My problem is I have no idea how to instantiate a List of VCards, like so:
List<VCard> vcards = null ;
I tried:
List<VCard> vcards = new List<VCard>();
but then it insists on implementing methods to look like this:
List<VCard> vcards = new List<VCard>() {
#Override
public void add(int location, VCard object) {
}
#Override
public boolean add(VCard object) {
return false;
}
#Override
public boolean addAll(int location, Collection<? extends VCard> collection) {
return false;
}
#Override
public boolean addAll(Collection<? extends VCard> collection) {
return false;
}
#Override
public void clear() {
}
#Override
public boolean contains(Object object) {
return false;
}
#Override
public boolean containsAll(Collection<?> collection) {
return false;
}
#Override
public VCard get(int location) {
return null;
}
#Override
public int indexOf(Object object) {
return 0;
}
#Override
public boolean isEmpty() {
return false;
}
#NonNull
#Override
public Iterator<VCard> iterator() {
return null;
}
#Override
public int lastIndexOf(Object object) {
return 0;
}
#Override
public ListIterator<VCard> listIterator() {
return null;
}
#NonNull
#Override
public ListIterator<VCard> listIterator(int location) {
return null;
}
#Override
public VCard remove(int location) {
return null;
}
#Override
public boolean remove(Object object) {
return false;
}
#Override
public boolean removeAll(Collection<?> collection) {
return false;
}
#Override
public boolean retainAll(Collection<?> collection) {
return false;
}
#Override
public VCard set(int location, VCard object) {
return null;
}
#Override
public int size() {
return 0;
}
#NonNull
#Override
public List<VCard> subList(int start, int end) {
return null;
}
#NonNull
#Override
public Object[] toArray() {
return new Object[0];
}
#NonNull
#Override
public <T> T[] toArray(T[] array) {
return null;
}
} ;
and when I try to add vcards to it, I get a NullPointerException. How do I solve this?
Try this
List<VCard> vcards = new ArrayList<VCard>();
Hope it helps.
I am trying to write an object in my startup activty to Parcel then send it to my Main activity using an intent. However I get a null pointer exception when retrieving the ParacelableArrayExtra in my Main activity. So i put in a check for null to handle the the null condition. However, the forecast Object does have data before being put into the intent so this condition should not be met.
I seems as though the Array of objects never gets put inside the intent. I this because I have my data being parceled incorrectly?
StartUpActivity.java
public class StartUpActivity extends AppCompatActivity {
public static final String FORECAST_KEY = "FORECAST_KEY";
private Forecast[] mForecasts;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new BackgroundTask(this).execute();
}
#Override
public void startActivityForResult(Intent intent, int requestCode) {
super.startActivityForResult(intent, requestCode);
}
private class BackgroundTask extends AsyncTask {
private Intent mIntent;
private Context mContext;
private static final String TAG = "BACKGROUND_TASK";
public BackgroundTask(Context context) {
mContext = context;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
mIntent = new Intent(StartUpActivity.this, MainActivity.class);
}
#Override
protected Object doInBackground(Object[] params) {
mForecasts = getForecasts();
return null;
}
#Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
// mForecasts is populated and does contain data
mIntent.putExtra(StartUpActivity.FORECAST_KEY, mForecasts);
// mForecasts in not located in mIntent
startActivity(mIntent);
finish();
}
// Other methods omitted
}
}
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
setSupportActionBar(mToolbar);
intent.getParcelableArrayExtra(StartUpActivity.FORECAST_KEY);
Parcelable[] allForecastParcelables = getIntent().getParcelableArrayExtra(StartUpActivity.FORECAST_KEY);
if (allForecastParcelables != null) {
mForecasts = new Forecast[allForecastParcelables.length];
for (int i = 0 ; i < allForecastParcelables.length; i++) {
mForecasts[i] = (Forecast) allForecastParcelables[i];
}
}
else {
mForecasts = null;
}
setupSlidingTabs();
}
Here are my Model objects that implement Parcelable
Forecast.java
public class Forecast implements Parcelable{
Day[] mDays;
public Day[] getDailyForecast() {
return mDays;
}
public void setDailyForecast(Day[] days) {
mDays = days;
}
#Override
public int describeContents() {
return 0;
}
public Forecast() {}
private Forecast(Parcel in) {
in.readTypedArray(mDays, Day.CREATOR);
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeTypedArray(mDays, flags);
}
public static final Creator<Forecast> CREATOR = new Creator<Forecast>() {
#Override
public Forecast createFromParcel(Parcel source) {
return new Forecast(source);
}
#Override
public Forecast[] newArray(int size) {
return new Forecast[size];
}
};
}
Day.java
public class Day implements Parcelable {
private Hour[] mHours;
private Average mAverage;
public Hour[] getHourlyForecast() {
return mHours;
}
public void setHourlyForecast(Hour[] hours) {
mHours = hours;
}
public Average getAverageForecast() {
return mAverage;
}
public void setAverageForecast(Average average) {
mAverage = average;
}
#Override
public int describeContents() {
return 0;
}
public Day() {}
private Day(Parcel in) {
in.readTypedArray(mHours, Hour.CREATOR);
mAverage = in.readParcelable(getClass().getClassLoader());
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeTypedArray(mHours, flags);
dest.writeParcelable(mAverage, flags);
}
public static final Creator<Day> CREATOR = new Creator<Day>() {
#Override
public Day createFromParcel(Parcel source) {
return new Day(source);
}
#Override
public Day[] newArray(int size) {
return new Day[size];
}
};
}
Average.java
public class Average implements Parcelable {
private String mWindCompassDireciton;
public String getWindCompassDireciton() {
return mWindCompassDireciton;
}
public void setWindCompassDireciton(String windCompassDireciton) {
mWindCompassDireciton = windCompassDireciton;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mWindCompassDireciton);
}
public Average() {}
private Average(Parcel in) {
mWindCompassDireciton = in.readString();
}
public static final Creator<Average> CREATOR = new Creator<Average>() {
#Override
public Average createFromParcel(Parcel source) {
return new Average(source);
}
#Override
public Average[] newArray(int size) {
return new Average[size];
}
};
}
And Hour is similar to average.java
Is there anything I am overlooking?
Each ArrayList and object inside the parcelable object should be peaceable too, Check this example. but i recommend you to send GSON and convert it to String and send it between activities as a string and convert it again to your object, Check this example.
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());
}
}