I am pretty new to android and trying to figure out delegation. To explain the same.
I have a search box for which I am defining a search text string as follows in class FragmentA:
protected EditText mSearchView;
Now, I have another class FragmentB extends Fragment A, which is using the same in a method as follows:
private void displayQuotes(final String searchAutoSuggestTitle, final String searchAutoSuggestSubTitle, final String searchAutoSuggestSymbol) {
killLastSearchAutoSuggestTask();
String text = mSearchView.getText().toString().toLowerCase() + " " + mSearchView.getText().toString().toLowerCase();
if(searchAutoSuggestSymbol.toLowerCase().contains(mSearchView.getText().toString().toLowerCase())){
QuotesFragmentWebView.newInstanceForSearch(getFragmentManager(), searchAutoSuggestSymbol, null);
}
else if(!searchAutoSuggestSymbol.toLowerCase().contains(text)){//mSearchView.getText().toString()))&&""&&(searchAutoSuggestSymbol.contains(mSearchView.getText().toString()))){
AnswersWebViewFragment.newInstanceForSearch(getFragmentManager(), searchAutoSuggestSymbol, null);
} else {
}
hideSearchView();
}
Now, the values are retrieved for mSearchView text for the text typed in. Now I have another class Fragment C which extends Fragment implements Onclicklistener,mainactivity, and no specific classes. I have a URL in there which I am defining as :
public final static String search_1_result = "https://mobile13.cp.com/fwd/results/answers/service/v1/?q="+mSearchView.getText().toString()+"%20revenue&ui.theme=novadark&uuid=PADACT-002";
But, I wonder how do I make it recognize the mSearchView.getText().toString() value(including recognizing mSearchView which it is throwing as an error,since its not defined in that specific class) . Also how do I carry on the typed value in Fragment B for the search, to be used in the url given above?
Thanks!
brian
Refer to this thread :
How do I use the parameter defined in another class?
I had a similar issue ,
You just need to define a function say
-public fragment(or your class can be your view class) extends whatever{
-public void thisfunction(){
//code to add
}
}
call that in the class you require and define the functionality in the main class from which you wish to delegate and call it inside the function referring to the fragment class.(exactly the same as in the class reference I gave you),don't forget to get the required listeners with implements functionality, in the example onrawerclosedlistener.
Related
I have multiple fragments in ViewPager. How can i get fragment first EditText Data to last Fragment?
I have set value in my first fragment like below -
txtConsAcNo.setText(account_no);
txtMeterSrMo.setText(mtr_serial_no);
Now i am getting this txtConsAcNo, txtMeterSrMo value on my last fragment like below-
ConDetFirstFragment f1 = new ConDetFirstFragment();
txtConsAcNo = f1.txtConsAcNo.getText().toString();
txtMeterSrMo = f1.txtMeterSrMo.getText().toString();
Now what i want that i am getting Null value and my app get unfortunately stopped. i want to get this data to my last fragment without bundle. how can i achieve this ?
Very Easy to Achieve this without Creating Interface, Bundle or intent -
I have declared all the variables in all the fragment "Public Static" like Below -
public static EditText txtConsAcNo, txtMeterSrMo;
After on any fragment i have declared variable to get data like below-
public static String txtConsAcNo,txtMeterSrMo;
Now i have created function to get value from first fragment in above variable below-
public static void getalldata(){
ConDetFirstFragment f1 = new ConDetFirstFragment();
txtConsAcNo = f1.txtConsAcNo.getText().toString();
txtMeterSrMo = f1.txtMeterSrMo.getText().toString();
}
Happy Coding...
There are a couple of problems here:
The first fragment may have been destroyed by the Android system to conserve memory.
Your fragments should not talk to each other directly
To achieve what you need, you need to jump through a few hoops.
Assuming that the source texts are EditText objects (ie. editable by the user), then add a TextWatcher to each of the EditText objects.
Create an Interface:
public interface TextPurveyor {
void setText1(String t);
String getText1();
void setText2(String t);
String getText1();
}
Implement this interface in the host Activity; and save the text values locally in the activity. Don't forget to save/restore them with the rest of the Activity state.
Make the TextWatcher objects call the appropriate setText(..) methods on the host activity:
((TextPurveyor)getActivity()).setText1(...);
Make each fragment check that the host activity implements this method.
When the second fragment wants a string, ask the activity for it:
((TextPurveyor)getActivity()).getText1();
To avoid coupling your project code tightly, try to use the design patterns that have been proven to work best like the Publisher/Subscriber as I will show you below:
There is a popular library I have always used in my projects called EventBus - just add the following to your build.gradle (module-level) file under dependencies :
compile 'org.greenrobot:eventbus:3.0.0'
Secondly, create a simple Plain Old Java Object (POJO) to represent your Event:
public class FragmentAToLastEvent{
private String txtConsAcNo;
private String txtMeterSrMo;
FragmentAToLastEvent(String acNo, String srMO){
this.txtConsAcNo = acNO;
this.txtMeterSrMo = srMO;
}
//getters and setters if needed
public String gettxtConsAcNo(){
return txtConsAcNo;
}
public String gettxtMeterSrMo(){
return txtMeterSrMo;
}
}
Next step is to actually use your Event class here:
So, in your fragment that you want to send text from EditText, simply do this:
String txtConsAcNo = f1.txtConsAcNo.getText().toString();
String txtMeterSrMo = f1.txtMeterSrMo.getText().toString();
EventBus.getDefault().post(new FragmentAToLastEvent(txtConsAcNo, txtMeterSrMo));
In your last fragment, simply do this to complete:
Inside onCreate or onAttach of your Fragment:
//register your event - making this class a subscriber
EventBus.getDefault().register(this)
//next, override a single method to receive the values you passed from above code (Fragment 1?)
public void onEvent(FragmentAToLastEvent event){
String txtConsAcNo = event.gettxtConsAcNo();
String txtMeterSrMo = event.gettxtMeterSrMo();
//now you can use your text here without problems!
}
Finally, remember to unregister inside onDestroy:
#Override
public void onDestroy(){
super.onDestroy();
EventBus.getDefault().unregister(this);
}
This is what I have always done and it is cleaner, without using interfaces that your fragments MUST implement and do all that!
I hope you find it helpful to you and good luck!
example:
Why can I write like that MainActivity.this.getContentResolve();
but can not write like that this.getContentResolve(); in MainActivity.java
If you need to access instance of enclosing class from inner class you need to make declaration like this - ClassName.this.anyClassMethod();
For more info read this article Nested Classes
This syntax becomes relevant when using inner classes.
public class A {
String str = "A";
public class B {
String str = "B";
public String getStr() {
return A.this.str; //returns A
}
}
}
It's long described but i think your question is related to anonymous class.
When you are inside class and want to refer to the current object of the class you can use this for example:
public class MyActivity extends Activity{
int foo;
public Test(int _foo){
this.foo = _foo;
}
}
but when you want to refer to the current class object from anonymous class inside it you should use class.this for example:
MyActivity.this
Full example for Inner Class:
public class Test {
int foo = 1;
public class InnerTest {
public String getFoo() {
return Test.this.foo;
}
}
}
Why can I write like that MainActivity.this.getContentResolve() but
can not write like that this.getContentResolve()?
Because your trying to access the context of outer class (MainActivity) in the inner class. we use TheActivityClassName.this in the inner class to access the outer TheActivityClassName class’s context.
When we are accessing the activity context in inner class we need a reference to the activity class name so we pass it like MainActivity.this
and when we need it in the class then we can reference it simply like this.something
You should have a look here to get good grasp on what context is actually
Hope it helps
There is no difference if you are calling getContentResolver() from any direct method of the activity. You can write both MainActivity.this.getContentResolver(); and this.getContentResolver(); as well as simply getContentResolver() with the same effect. In this case, the this keyword refers to the current instance of the MainActivity.
However, if you are within an inner class or inside an implementation of an interface/abstract method inside the MainActivity, then this will refer to an instance of the inner class or the interface you are implementing. In that case, you have to call MainActivity.this to get access to the instance of the MainActivity.
I am basically creating a base class that will overwrite (extend) classes such as Activity or FragmentActivity and add custom functionality by defining methods that should be available to any other class, that extends this base class.
The structure if the following, basically:
CustomActivity (extends)->BaseActivity (extends)->Activity
or
CustomActivity (extends)->BaseFragmentActivity (extends)->FragmentActivity
The base class in this situation is called hmFragmentActivity and it extends FragmentActivity. I've defined a custom method inside hmFragmentActivity:
public String pref(String key, String defaultVal) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
return prefs.getString(key, defaultVal);
}
Basically it's a helper method, which I want available in all other activities, by making them extend hmFragmentActivity instead of FragmentActivity.
However, when I try to call prefs() from any activity, it gets highlighted as an error in the IDE.
Here's an example:
public class FuelEconomy extends hmFragmentActivity {
// In some method:
if(pref("fuel_usage_liter", "")==""){
Log.d("fuel", "Fuel set");
}
}
When I highlight pref() above, the IDE says:
Cannot make a static reference to the non-static method pref(String)
from the type hmFragmentActivity
I have a problem about setting a TextView from a class which is not a child class of Activity. This class is basically used for handling registration and REST request with 3rd party server.
After getting textfield info from 3rd Party server, it is too late to set TextView in the Main Activity.
I can't use SharedPreferences to set this info, because MainActivity has already started.
I can't pass this info with Bundle since my java class is not an activity class.
How can I pass this info and set the TextView in the MainActivity? Is there any way to do this?
The proper way of doing this this is to create a listener.
Create an interface :
public interface OperationCompletedListener{
void onOperationCompleted(String resultValue);
}
Then in your class which calls Rest services, create a variable for this listener and a method to set it.
private OperationCompletedListener mListener;
public void setOperationCompletedListener(OperationCompletedListener listener){
mListener=listener;
}
Then when the your rest service completed call like below :
if(mListener!=null){
mListener.onOperationCompleted("your value to be passed");
}
Then in your activity class which contains the TextView, create an object of OperationCompletedListener and set it to the other class using the set method that we created earlier. Then in the onOperationCompleted method, set the text view with your value and you are done.
private OperationCompletedListener mOperationCompletedListener=new OperationCompletedListener() {
#Override
public void onOperationCompleted(String resultValue) {
yourTextView.setText(resultValue);
}
};
restServiceClassObject.setOperationCompletedListener(mOperationCompletedListener);
You can create an static method which update textview in your activity class . Then call this method from your other class whenever you want.
Try to pass the Activity to the non-Activity class when you instantiate it. For example:
public class NonActivityClass {
private Activity parentActivity;
public NonActivity(Activity parentActivity) {
this.parentActivity = parentActivity;
}
}
Or you can just pass the Activity to a static method in your NonActivityClass if you don't want to instantiate it (it's abstract). Then, you can inflate the TextView or do a findViewById from the parent and set the text.
From my experience, you should never use a static non-final variable to maintain a reference across activities. When you restart the app or the phone, or when Android kills your app's process, the reference and state of the variable becomes lost and may cause your app to crash.
For every Activity I add to my app I'm noticing a lot of similar code being used in the initialization of the Activity. A helper class with a static method to wrap this similar code seems the way to go.
I first thought of a singleton class. I could add static methods/variables and use them across the application. I haven't really tried to see how would this work in an Android application. Searching a little bit more I saw something about creating a class extending Application. For this I did a simple test:
public class MyApp extends Application {
public static String DEMOTEXT = "WORKING!";
public static void ShowToast(Context context, String text) {
Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
}
}
MyApp.ShowToast(this, MyApp.DEMOTEXT); // Placed on onCreate of some Activity
This works exactly as I expected. Is this the way to go on Android or is there a better convention? Anything else I should consider when doing this?
By the way, should I use the final keyword on the string? What about the method?
EDIT: I just read this:
There is normally no need to subclass Application. In most situation,
static singletons can provide the same functionality in a more modular
way. If your singleton needs a global context (for example to register
broadcast receivers), the function to retrieve it can be given a
Context which internally uses Context.getApplicationContext() when
first constructing the singleton.
http://developer.android.com/reference/android/app/Application.html
Should I use a singleton then?
Application is primarily used for a global application initialization. You would create your own class, override Application.onCreate() and initialize your static application data there.
Dont forget to declare it in the AndroidMainfest.xml:
<application
android:icon="#drawable/icon"
android:label="#string/app_name"
android:name="your.package.path.to.MyApp">
A static helper class is made the way you did.
The convention is to use lower case letter at first position, so MyApp.showToast(...).
You would use final for the String if you would want to avoid madifications on other places (since it should be a contant).
// this would allow ...
public static String DEMOTEXT = "WORKING!";
// ... to do this somewhere else
MyApp.DEMOTEXT = "NOT WORKING!"
I haven't tried this but I think you should be able to do something like this as well.
public class MyActivity extends Activity {
private static final String DEMOTEXT = "WORKING!";
#Override
public void onCreate(Bundle bundle)
{
super.onCreate(bundle);
Toast.makeText(this, DEMOTEXT, Toast.LENGTH_SHORT).show();
}
}
Now for all activities that need to use that initialization could just extend your base activity class.
public class SomeActivity extends MyActivity {
...
// Should display the toast on create
...
}
Yes just use a singleton. Well in this case if your methods are static, you don't even need a singleton. Just a class with static methods.