Safest approach for holding an instance of Activity - android

What is the best and safer approach for holding an instance of the Activity
private Activity mActivity;
First approach:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivity = getActivity();
}
Second approach:
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.from(getActivity()).inflate(R.layout.fragment_main, container, false);
mActivity = (Activity) view.getContext();
return view;
}

Well, it depends. I would advice you to use getActivity().
You can use it after onAttach(Activity activity). If you look at the FragmentManager source code, you can see there, that the mActivity field of Fragment is set just before calling onAttach.
But you have to be careful, the activity is not fully initialized (views,..) before onActivityCreated gets called.

In most cases, you should not need to catch Activity.
But if you want to, my suggestion is,
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mActivity = this;
}

Related

Robospice lifecycle in fragment

So far, i was using Volley but after going through the Robospice library, and it's advantages over other network libraries, i started using it in my current project.
It working fine, but since it's lifecycle is tied to the activity not fragments, i implemented the same in fragment like this.
public class MainActivityFragment extends Fragment {
private SpiceManager spiceManager = new SpiceManager(JacksonSpringAndroidSpiceService.class);
private static final String KEY_LAST_REQUEST_CACHE_KEY = "lastRequestCacheKey";
private String lastRequestCacheKey;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
performRequest(mSort);
return rootView;
}
#Override
public void onSaveInstanceState(Bundle outState) {
if (!TextUtils.isEmpty(lastRequestCacheKey)) {
outState.putString(KEY_LAST_REQUEST_CACHE_KEY, lastRequestCacheKey);
}
super.onSaveInstanceState(outState);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
if (savedInstanceState != null && savedInstanceState.containsKey(KEY_LAST_REQUEST_CACHE_KEY)) {
lastRequestCacheKey = savedInstanceState.getString(KEY_LAST_REQUEST_CACHE_KEY);
spiceManager.addListenerIfPending(MovieDataResult.class, lastRequestCacheKey,
new ListMovieRequestDataListener(movieImageAdapter, getActivity(),progressDialog));
spiceManager.getFromCache(MovieDataResult.class, lastRequestCacheKey, DurationInMillis.ONE_MINUTE,
new ListMovieRequestDataListener(movieImageAdapter, getActivity(),progressDialog));
}
super.onActivityCreated(savedInstanceState);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
spiceManager.start(getActivity());
}
#Override
public void onStop() {
super.onStop();
if (spiceManager.isStarted()) {
spiceManager.shouldStop();
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
mSort = Utility.getPreferredSorting(getActivity());
setUpProgressDialog();
}
private void performRequest(String mSort) {
MovieDataRequest movieDataRequest = new MovieDataRequest(apiKey,mSort);
lastRequestCacheKey = movieDataRequest.createCacheKey();
spiceManager.execute(movieDataRequest, lastRequestCacheKey,
DurationInMillis.ONE_MINUTE, new ListMovieRequestDataListener(movieImageAdapter, getActivity(),progressDialog));
}
}
This works fine, i was wondering, if it follows the lifecycle. As, i am starting spicemanager onAttach() and stopping onStop() and onRestoreInstance() getting the cached data.
Basically, this is how it works here-->
spicemanager starts when fragment is attached
then .execute() is called for network request
spicemanager is destroyed onStop()
Also, is it a good approach to have a spicemanager for each activity?
I also pondered about this question recently as I was creating spiceManagers in both my activities and fragment classes.
This actually results in me having spiceManager objects in multiple places and for me, I do not think it was the most efficient way to do things.
Eventually, what I decided to do was to create a static instance of the spiceManager in my activity:
public static SpiceManager spiceManager = new SpiceManager(SpiceService.class);
Then use this static spiceManager within my fragments:
MainActivity.spiceManager.start(getActivity());
I also think that the most efficient way to do this is probably if you use interfaces to transfer data that you want handled by robospice back to the activity and just use the spiceManager inside your activity to do all the work. However, this can be a major piece of work.

Use Activity method in Fragment class

I am new in Fragment and I am trying use Activity method in Fragment class. So please help me how I use Activity method in Fragment. And also how I use List<NameValuePair>, SharedPreferences in Fragment.
public class DashboardFragment extends Fragment {
public DashboardFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_dashboard, container, false);
return rootView;
}
This is Fragment code and I want to use Activity method in this. So please help I am new in this section. If there is another method, please tell me.
After the fragment's onAttach method is called (see Fragment lifecycle), you can obtain a reference to the activity through fragment's getActivity() method. Then you can cast this reference to the type of your activity and call the method:
((MyActivity)getActivity()).method();
Your activity method needs to be static and public. Then you could do following in your Fragment:
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof MyActivity) {
this.activity = activity;
sharedPreferences = activity.getSharedPreferences(...);
}
}
Declare MyActivity activity in your Fragment.
then you can call activity.yourMethod() in another place. Dont forget to check if activity is null.
Use an interface implementation for this. Somethings like this:
Activity:
MyActivity extends AppCompatActivity implements CallBack {
#Override
public void onCallBack() {
// do something
}
}
And Fragment:
MyFragment extends Fragment {
public interface CallBack {
void onCallBack();
}
private CallBack callBack;
#Override
public void onAttach(Activity context) {
callBack = (CallBack) activity;
}
// when clicking or whatever it takes to call
callBack.onCallBack();
}
1) You can get Activity instance with getActivity() method in Fragment:
Activity activity = getActivity();
Then you can call any Activity method with the instance:
activity.method();
2) About SharedPreferences, you can also get Context instance with getContext() method in Fragment.
Context context = getContext();
So you can call getSharedPreferences() method with the instance:
SharedPreferences sharedPreferences = context.getSharedPreferences(String name, int mode);
3) List<T> is a pure Java class. So you can use it in Fragment without any limitation.

#OnClick doesn't works after rotation in ButterKnife

I have the next fragment:
public class MyFragment extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.my_fragment, container, false);
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
ButterKnife.setDebug(true);
ButterKnife.bind(this, view);
}
#OnClick(R.id.button)
public void onButtonClicked () {
//Do some stuff
}
}
OnClick method works like a charm first time and it works fine until I rotate the device. When I rotate the device, method doesn't works more.
Log has no errors.
Do you know what is the problem?
Thanks you.
Try to retain the fragment to avoid to be destroyed and created again.It may resolve you problem
Try unbinding when the fragment is destroyed (which should happen upon rotation). Then it should bind correctly again:
#Override
public void onDestroyView(){
super.onDestroyView();
ButterKnife.unbind(this);
}

getActivity return null in fragment onActivityCreated in some rooted device

My app work fine on most device but some rooted device. In fragment onActivityCreated, getActivity keep return null. I need Context class to to set up thing below.
So anyone can help me?
Update
public class BaseProductFragment extends Fragment {
...
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(layout_id, container,
false);
return rootView;
}
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ImageCacheParams cacheParams = new ImageCacheParams(getActivity(),
Utils.PRODUCTS_CACHE_DIR);
....
}
getActivity "might" return null if called from within onActivityCreated...especially during a configuration change like orientation change because the activity gets destroyed...move that initialization to onAttach...
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
//initialize here
}
onActivityCreated is a called when the parent activity's onCreate is called...but remember that it could be "recreated", destroyed during a config change

Passing Arguments to a Fragment via Bundles

Bundle params=new Bundle();
params.putBoolean("isNew", true);
getFragmentManager().beginTransaction()
.replace(R.id.main, Fragment
.instantiate(LandingScreen.this, "com.fragments.FragmentOne",params)).commit()
Now this is Fragment1
public class FragmentOne extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_one, null);
return root;
}
}
Where do i receive the Bundle params, that i sent with when creating this Fragment ?
Kind Regards
You'll receive Bundle in Fragment onCreate(....)
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
boolean isNew=this.getArguments().getBoolean("isNew");
}
You can get the data where Bundle object is accessible as a parameter
onCreate()
onCreateView()
onActivityCreated()
When you use onCreate()
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_layout);
String myData=this.getArguments().getString("myData");
}
When you use onCreateView()
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
String myData=this.getArguments().getString("myData");
return inflater.inflate(R.layout.example_fragment, container, false);
}
When you use onActivityCreated()
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
String myData=this.getArguments().getString("myData");
}
Most of the time, you'll use call getArguments() in onCreate(), which gets called sometime after you instantiate the Fragment but before onCreateView() and onActivityCreated() would get called. However, as per Android documentation, if you're calling this from your Activity while it's being created, you're not guaranteed that the Activity has finished initializing before onCreate() is called:
Note that this can be called while the fragment's activity is still in the process of being created. As such, you can not rely on things like the activity's content view hierarchy being initialized at this point. If you want to do work once the activity itself is created, see onActivityCreated(Bundle).
For more information, check out this blog post on Activities and Fragments: http://www.zerotohired.com/2015/02/passing-data-between-activities-and-fragments-in-android.

Categories

Resources