android how to get value from the interface - java

I am getting values in broadcast receiver in MyFragment class which extends the interface DelayTime as -
if(intent.getAction().equals(BroadcastHelper.DEPARTURE_TIME)){
Bundle args = intent.getExtras();
if (args != null) {
int departure_time = args.getInt("Departure");
DepartureTime(departure_time);
}
}
else if(intent.getAction().equals(BroadcastHelper.ARRIVAL_TIME)){
Bundle args = intent.getExtras();
if (args != null) {
int arrival_time = args.getInt("Arrival");
ArrivalTime(arrival_time);
}
}
#Override
public int ArrivalTime(int arrival_time){
//what to do here
Log.d("hi","arrival_time" + arrival_time);
return arrival_time;
}
#Override
public int DepartureTime(int departure_time){
//what to do here
return departure_time;
}
I have an interface DelayTime -
public interface DelayTime {
public int ArrivalTime(int arrival_time);
public int DepartureTime(int departure_time);
}
I need to get the values from MyFragment class in MyOwn Class using the interface. In MyOwn class, the implementation which I have done is like -
DelayTime delaytime = new MyFragment();
int arri = delaytime.ArrivalTime(arr);
Log.d("hi","arrival 0" + arri);
myAdapter.setArrTime(arri); //Null pointer here
The value of arri is 0. The logs are like -
arrival_time 4500
arrival_time 0

Your interface DelayTime should look like this, for standards:
public interface Delayer {
void setArrivalTime(int arrivalTime);
void setDepartureTime(int departureTime);
}
When instantiating your MyOwn class you should pass MyFragment in its constructor and save a reference to it.
MyOwn mClass = new MyOwn((DelayTime) mFragment);
In the MyOwn class the constructor should be something like:
public MyOwn(DelayTime fragmentInterface) {
this.fragmentInterface = fragmentInterface;
}
Have the MyOwn class consume the interface methods:
public void setArrivalTime(int arrivalTime) {
fragmentInterface.setArrivalTime(arrivalTime);
}
And use the interface with your MyOwn object like this:
mClass.setArrivalTime(yourValue);
Also note that fragments are used with the (support) fragment manager and not instantiated directly like that.
I suggest you have a read here: https://developer.android.com/guide/components/fragments.html

Related

How to Pass a Value from One Activity to Another Activity/Adapter

Iam trying to pass a value my Cartadapter to CartActivity.
My code is as follows:
CartActivity.java:
cartTotalChanged((cartAdapter.getTotal()));
CartAdapter.java:
public Double getTotal() {
Double total = 0d;
try{
for (MenuItem item : dataList)
total += item.getTotal();
}
catch(Exception e){
return total;
}
finally{
return total;
}
}
cartTotalChanged Function:
public void cartTotalChanged(Double totalAmount) {
if (coupon != null) {
totalAmount = totalAmount - (coupon.getType().equals("fixed") ? coupon.getReward() : ((totalAmount * coupon.getReward()) / 100));
}
DecimalFormat decimalFormat = new DecimalFormat("###.##");
subtotal.setText(decimalFormat.format(totalAmount) + currency);
double sc = (totalAmount * serviceCharge / 100);
feeService.setText(decimalFormat.format(sc) + currency);
total.setText(decimalFormat.format(totalAmount > 0 ? (totalAmount + sc + deliveryFee) : 0) + currency);
Helper.setCart(sharedPreferenceUtil, cartItems);
}
My problem here is cartTotalChanged((cartAdapter.getTotal())); is returning a Null and My app crashed with multiple thread failure.
kindly help
To pass data from adapter to activity use following way:
1.use Interface to create new interface class.
2.In activity implement that interface class and override passing data method.
3.In adapter class assign variable as inside parameter to interface method
Interface class:
Class Ainterface
{
public void passData(String setData);
}
Adapterclass:
Ainterface ainterface;
Adapterclass(Context context)
{
ainterface=context;
}
/*add below line in your onbind or onclick... whenever you want to pass data from adpter to activity use below line*/
ainterface.passData("set your variable which is load to activity");
Activity class:
Class MainActivity implements Ainterface
{
/*inside onCreate */
AdapterClass ac=new AdapterClass(this);
public void passData(String getdata)
{
Log.v("String is",getdata);
/*do something*/
}
}
i hope its work on you
You can create a class like below:
public class Globals{
private static Globals instance;
// Global variable
private Double cartTotal;
// Restrict the constructor from being instantiated
private Globals(){}
public void setData(Double d){
this.cartTotal=d;
}
public Double getData(){
return this.cartTotal;
}
public static synchronized Globals getInstance(){
if(instance==null){
instance=new Globals();
}
return instance;
}
}
Then on your adapter set it like this:
Globals g = Globals.getInstance();
g.setData(cartTotal);
And receive in your Activity as:
Globals g = Globals.getInstance();
Double cartTotal = g.getData();
You can set a number of Global variables like this as per your requirement.
Hope this helps !!

Modify variables in an instance from another class Android

I simplified this for brevity; hopefully this example isn't actually functional. I'm creating and doing things with a variable, then I'm having another class do some stuff, then that class refers back to the original and tells it to do more stuff with that variable.
I've done exactly this with views. I simply pass the activity and then when I need to use it I use activity.findViewById(id) to do stuff. With variables, you can't just do activity.variable. I tried using a getter (as shown in this example), but maybe I'm still just doing it wrong or it can't be done how I'd like:
public class MyActivity {
private int test;
public void onCreate(Bundle savedInstanceState) {
test = 5;
int data = 100;
//Pass something to it
new NotAnActivity().func(MyActivity.this,data);
}
public int gettest() {
return test;
}
public void func(Activity instance, int response) {
int test = new MyActivity().gettest();
//Do stuff with test
}
}
public class NotAnActivity {
public void func(Activity instance, int data) {
//Do stuff with data
int response = 20;
//Try to pass information back
new MyActivity().func(instance,response);
}
}
You can't use a activity.gettest() because you're passing the superclass Activity between classes. To have access to the gettest() method you need to pass the specific child activity (MyActivity extends Activity, pass MyActivity instead of Activity) or you can cast to your specific activity.
((MyActivity)activity).getter();
So here, instead of:
public void func(Activity instance, int data) {
//Do stuff with data
int test = ((MyActivity)instance).gettest();
}
or
public void func(MyActivity instance, int data) {
//Do stuff with data
int test = instance.gettest();
}
It's not a good idea to instantiate your activities yourself new A()
public class MainActivity extends AppCompatActivity {
private int test;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
test = 5;
int data = 100;
new NotAnActivity().func(this,data);
}
public int gettest() {
return test;
}
public void func(MainActivity instance, int response) {
//int test = new MainActivity().gettest();
int test = instance.gettest();
Log.v("variable", "test = " + test);
}
}
class NotAnActivity {
public void func(MainActivity instance, int data) {
//Do stuff with data
int response = 20;
//Try to pass information back
instance.func(instance,response);
}
}
You can try it. Your mistake is [new MyActivity()]

Is my method to update textview from a volley response the 'Android way' the right way?

I have a fragment that sets the textViews from a data object. This data object is initially null when the fragment is created but gets updated after a network request. Now to update the textviews I create a function 'updateAll' and pass the fragment to the callback function that handles the network response. And once the data is set to the data object I call 'updateAll' from the fragment reference.
Example :
class someFragment extends Fragment {
private Textview foo;
private dataObject obj;
...
public onCreate(...) {
this.obj = new dataObject();
sendRequestToVolley(..., new VolleyCallbacks(this));
}
public onCreateView(...) {
...
foo.setText(obj.someVar);
}
public void updateAll() {
foo.setText(obj.someVar);
}
}
class VolleyCallbacks implements someInterface {
public VolleyCallbacks(someFragmment fragment, dataObject obj) {
this.obj = obj;
this.fragment = fragment;
}
public onSuccess(Response r) {
obj.updateData(r);
this.fragment.updateAll();
}
}
Is this the correct way to do this? Is there a better method?
You code looks mainly good. I see one issue: you're keeping the Fragment as a strong reference. It can generate a memory leak if the fragment is destroyed (ie. the user presses back) before the network call is completed. To prevent that, you should use a WeakReference.
I also wouldn't modify your data object inside the callback class. It's better to let the fragment modify it since he is the one holding the reference to it.
I would transform your code like that:
public class SomeFragment extends Fragment {
private Textview foo;
private dataObject obj;
...
public onCreate(...) {
this.obj = new dataObject();
sendRequestToVolley(..., new VolleyCallbacks(this));
}
public onCreateView(...) {
...
refreshTextView();
}
private void refreshTextView() {
foo.setText(obj.someVar);
}
void onRequestSuccess(Response r) {
obj.updateData(r);
refreshTextView();
}
}
class VolleyCallbacks implements SomeInterface {
private WeakReference<SomeFragment> fragmentWeak;
public VolleyCallbacks(SomeFragment fragment) {
this.fragmentWeak = new WeakReference<>(fragment);
}
public onSuccess(Response r) {
SomeFragment fragment = this.fragmentWeak.get();
if (fragment != null) {
fragment.onRequestSuccess(r);
}
}
}

How do I save the Custom Spinner state

I extended android.widget.Spinner. and added an int field to my implementation. Now I want it to save the field value on orientation change. My first thought was using Bundle object for that:
override fun onSaveInstanceState(): Parcelable {
val bundle = Bundle()
bundle.putParcelable(SUPER_STATE, super.onSaveInstanceState())
bundle.putInt(PREV_ITEM, this.prevItem) // ... save stuff
return bundle
}
override fun onRestoreInstanceState(state: Parcelable?) {
val newState: Parcelable
if (state is Bundle) {
this.prevItem = state.getInt(PREV_ITEM) // ... load stuff
newState = state.getParcelable<Parcelable>(SUPER_STATE)
super.onRestoreInstanceState(newState)
}
super.onRestoreInstanceState(state)
}
But I get an error:
java.lang.ClassCastException: android.os.Bundle cannot be cast to android.widget.Spinner$SavedState
So I found Spinner source code and figured out that I have to extend inner static class SavedState and use it to save my field value. But I wasn't able to do that. Android Studio suggests that it "Cannot resolve symbol 'Saved State'".
So what do I do to save the state of my custom Spinner?
You cannot actually extend Spinner.SavedState because it created inside Spinner class. Even if you try to override Spinner.onSaveInstanceState you cannot implement this method in your custom class, because you don't have access to private variables of Spinner class.
What you can actually do is to create new class implementing Parcelable and use value returned from base class to construct your own class.
#Override
public Parcelable onSaveInstanceState() {
final MySavedState ss = new MySavedState(super.onSaveInstanceState());
ss.myInt = 100;
return ss;
}
#Override
public void onRestoreInstanceState(Parcelable state) {
MySavedState ss = (MySavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
if(ss.myInt == 100) {
Log.d("TAG", "Success!");
}
}
static class MySavedState extends Spinner.BaseSavedState {
int myInt;
public MySavedState(Parcelable superState) {
super(superState);
}
public MySavedState(Parcel source) {
super(source);
myInt = source.readInt();
}
}

pass Object to another activity

I have found this way to do this
Student student = new Student (18,"Z r");
Intent i = new Intent(this, B.class);
i.putExtra("studentObject", student);
startActivity(i);
The problem is that if the object changed in the first activity No change took place in the another activity.
I thought how to make it like a constructor that no copy of the object is pass but the object it self.
Thanks
How about if you configure the "object" as a singleton of the entire application? This way, everybody (your app) sees the changes... See some insights here: http://developer.android.com/guide/faq/framework.html#3
For example, in some other file (Student.java):
public class Student {
public String Name;
}
Create a custom application class:
public MyApp extends Application {
private Student obj = new Student();
public Student getMyObject() {
return obj;
}
}
Anywhere in your application (e.g. SomeActivity.java):
Student appStudent = ((MyApp) getActivity().getApplicationContext()).getMyObject();
appStudent.Name = "New Name"; // "global" update
You could also look into a BroadcastReceiver. With a BroadcastReceiver you can send a message from one Activity to another and with an interface you can pass the object from one Activity to the other.
I think this is a great example, where a BroadcastReceiver is created to check the internet connection of the device. But you can easily convert this in a BroadcastReceiver with your own custom action to send the object.
Implement parcelable in your student class and you can copy the student into the intent.
How can I make my custom objects Parcelable?
Code works with parcelable classes
> Student student = new Student (18,"Zar E Ahmer"); Intent i = new
> Intent(this, B.class); i.putExtra("studentObject", student);
> startActivity(i);
Below is an example of bean class I use that implements parcelable. Here you would replace KmlMarkerOptions with Student
#SuppressLint("ParcelCreator")
public class KmlMarkerOptions implements Parcelable {
public MarkerOptions markeroptions = new MarkerOptions();
public String href = "";
public int hrefhash =-1;
public String id = "";
public long imageId = -1;
public int locationId = -1;
public int markerSize = -1;
public KmlMarkerOptions(){
}
public KmlMarkerOptions(Parcel in) {
this.markeroptions = in.readParcelable(null);
this.href = in.readString();
this.hrefhash = in.readInt();
this.id = in.readString();
this.imageId = in.readLong();
this.locationId = in.readInt();
this.markerSize = in.readInt();
}
#SuppressWarnings("rawtypes")
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public KmlSummary createFromParcel(Parcel in) {
return new KmlSummary(in);
}
public KmlSummary[] newArray(int size) {
return new KmlSummary[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(markeroptions, 0);
dest.writeString(href);
dest.writeInt(hrefhash);
dest.writeString(id);
dest.writeLong(imageId);
dest.writeInt(locationId);
dest.writeInt(markerSize);
}
}

Categories