How do we cast context to fragment reference? - android

I have a class 'Common' and a fragment 'FragmentTest'. The 'Common.java' is a general class that have some common functions for other activities..Those functions are accessed by context of each activities.. And here I am passing the fragment's context to a function in that class. I am doing like this
In Fragment :-
Common commonObj = new Common();
commonObj.myfunction(this.getActivity(),"Do you want to Update ?");
And in Class after some operation i'm trying to return back to fragment class.Like this
:-
public void myfunction(Context context , String str){
//....//
if(context.getClass().isInstance(FragmentTest.class)){
**FragmentTest mContext = (FragmentTest)context;**
mContext.FunctionInFragment();
}
}
But i have error in this..Because i cannot cast the context to fragment reference.
Somebody please help..

Firstly you can't cast a Context to a Fragment as Fragment doesn't extend Context. Activity does extend Context which is why when you do this from an Activity what you are trying works.
I'd suggest ideally that the methods in your Common class should be totally unaware of the existence of your Fragment. This way they are not 'coupled' together. To achieve this you can use a callback interface.
Create an interface as follows:
public interface Callback<T> {
onNext(T result);
}
Then you can change your method in Common to the following:
public void myfunction(Callback<Void> callback , String str){
//....//
callback.onNext(null);
}
Then when you call the method in Common from the Fragment you would do it like this:
Common commonObj = new Common();
commonObj.myfunction(
new Callback<Void>() {
#Override
public void onNext(Void result) {
functionInFragment();
}
},
"Do you want to Update ?"
);
If you needed to send data back to the function then you can change the return type of the callback. For instance if you wanted to pass back a string you would use Callback<String> and then the method in the original call would look like this:
new Callback<String>() {
#Override
public void onNext(String result) {
}
}
And in your Common class you would call it like this:
public void myfunction(Callback<String> callback , String str){
//....//
String result = "Hello from common";
callback.onNext(result);
}

You can do something like this:
public void myfunction(BaseFragment fragment, String str){
//....//
if(fragment.getClass().isInstance(FragmentTest.class)){
FragmentTest fr = (FragmentTest) fragment;
fr.FunctionInFragment();
}
}
i.e. using some base fragment(BaseFragment) and inherit from it.

Related

How to get context in moxy presenter android

How do I can get activity context from Moxy presenter?
At first sight it's very easy...: 1. Add Context getMvpActivity (); into MvpView interface and implement it in Acivity.
2. And in a presenter call getViewState().getMvpActivity().
But Moxy don't allow to add the non-void methods to MvpView interface.
Pls help me.
P.S. I need context in the Presenter to init App Component(activity is a param for static getter).
Thanks. Sorry for some grammar mistakes.
Right solution is not using activity context in the presenter. Because, in case of activity recreation, this context will leak (because presenter will be still alive). You able to use application context. You can pass it through presenter's constructor.
Solved this problem with adding a Activity context as a param into onViewCreated().
Like this:
//presenter super class
public void onViewCreated (Activity activity) {
//init component here
//this.component = ...
injectPresenter ();
}
protected PresenterComponent getComponent () {
return this.component;
}
protected abstract void injectPresenter ();
//presenter child class
#Override
public void onViewCreated (Activity activity) {
super.onViewCreated(this);
}
#Override
protected void injectPresenter () {
//you can name "inject" different ways
//in your presenter component interface
getComponent().inject(this);
}
//activity class
#Override
protected void onCreate () {
//P.S.(for beginners) variable presenter is the object of class
//which extends Presenter super class
presenter.onViewCreated(this);
}

Mock activity class member before onCreate

I am trying to test an activity using robolectric 3.3.2.
Want to mock and activity's member initialization as the direct call results in NPE.
ActivityController<MyActivity> activityController =
Robolectric.buildActivity(MyActivity.class);
mTestActivity = activityController.get();
Mockito.when(mTestActivity.getCountry()).thenReturn("xxxx");
activityController.setup();
Tried out above code, but the setup.() (oncreate) ignores the mock of
getCountry method and invokes the definition from activity.
Is there a way to achieve this?
It will not work like this even if you use spies (#Spy, Mockito.spy()).
You should use stub:
public class MyActivityTest{
public static class StubMyActivity extends MyActivity {
Country getCountry() {
return someSpecialCountry;
}
}
#Before
public void setUp(){
ActivityController<StubMyActivity> activityController =
Robolectric.buildActivity(StubMyActivity.class);
mTestActivity = activityController.setup().get();
}
}

android passing data from class to activity

I have been looking for a long time for a simple way to pass data (string type) from class to activity.
I found some tutorials about passing data from activity to class but is it possible to do the opposite, passing data from class to activity ?
if you import the class in your activity (which is also a class by the way) you can easily access the classes attributes.
example: MyClass.java
package edu.user.yourappname;
public class MyClass {
public string infoToPass = "whatever";
}
MyActivity.java
package edu.user.yourappname;
import edu.user.yourappname.MyClass
public class MyActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
String myString = MyClass.infoToPass;
}
}
i have no IDE to type this in atm it might contain some errors :S but i hope you get the idea.
if you need more specific help you have to provide a code sample.
also, what do you want to achieve exactly? maybie there's a different approach.
cheers!
Create Interface and implement that in your activity. Pass the activity instance in your class and and call that instance with interface method whenever you like.
To be more clear, create an interface and use it as following:
public interface SomeInterface{
public void passValue(String value);
}
public SomeActivity extends Activity implements SomeInterface{
// place any code you want in your activity, onCreate, onResume, etc.
private void someMethod(){
// Wherever in your activity, initialize your class with your activity.
SomeClass someClass = new SomeClass(this);
someClass.someMethod();
}
public void passValue(String value){
// do whatever you want with your value
}
}
public class SomeClass{
private SomeInterface someInterfaceInstance;
public SomeClass(SomeInterface someInterfaceInstance){
this.someInterfaceInstance = someInterfaceInstance;
}
public void someMethod(){
// Some code...
someInterfaceInstance.passValue("Hello World!");
// Some more code...
}
}
Here is a easy way of doing it -
By defining static variables
In your class, make the String whose value you want to pass public static like this -
public static String pass;
And then in you activity, you can directly access it since it's a public variable like this -
String receive = className.pass;

how to use interface for communicatiion among classes and activities

I have a class and an activity. I need to implement an interface to track whenever there is a change in a variable in class then it should reflect on activity. Can someone please explain how to use interface for this purpose?
You can use this code for reference, create interface to trace event, implement that interface in your activity and set its call back from change var value event of your class.
interface ChangeListener{
public void onVarChanged(String value);
}
class Abc{
String var ="";
ChangeListener changeListeners;
public Abc(ChangeListener changeListeners){
this.changeListeners = changeListeners;
}
public void setVar(String str){
var = str;
changeListeners.onVarChanged(var);
}
}
class MyActivity extends Activity implements ChangeListner{
/*
your stuff...........
*/
onCreate(...){
Abc abc = new Abc(this);
abc.setVar("My new string");
}
#Override
public void onVarChanged(String value)
{
Log.v("","==== Variable is changed ==== "+value);
}
}
Observer pattern is the right fit here. Have a look at this http://developer.android.com/reference/java/util/Observable.html . The activity will be an Observer and the other class will be the Observable

How to desing a reusable DialogFragment

There is some questions already close to this question but they haven't been very helpful for me. So here comes a new one.
I have an Activity which has two tabs. Each tab contains a ListFragment (SherlockListFragment to be exact). One tab shows a list of shopping list objects and the other shows a list of recipe objects. Now I want to create a DialogFragment for renaming a list or a recipe or any other object I might later add to the application.
The solution provided here sounded promising but because ListFragment can not be registered to listen clicks from the dialog I should make my Activity to listen them which is not ideal because then my Fragments would not be independent.
How to get data out of a general-purpose dialog class
Ideally I would like to have my rename dialog as independent and reusable as possible. This far I have invented just one way to do this. Sending the objects className and id to the dialog and then using switch case to fetch the correct object from the database. This way the dialog would be able to update the objects name by itself (if the object has rename method). But the requery to the database sounds just dump because the ListFragment has the object already. And then the dialog would need a new case in the switch for each new kind of object.
Any ideas?
I actually just created a similar sort of dialog fragment to what you're asking about. I was for a fairly large app and it was getting kind of ridiculous the amount of dialog listeners our main activity was extending just to listen for the results of a single dialog.
In order to make something a bit more flexible I turned to using ListenableFuture from Google's Guava concurrent library.
I created the following abstract class to use:
public abstract class ListenableDialogFragment<T> extends DialogFragment implements ListenableFuture<T> {
private SettableFuture<T> _settableFuture;
public ListenableDialogFragment() {
_settableFuture = SettableFuture.create();
}
#Override
public void addListener(Runnable runnable, Executor executor) {
_settableFuture.addListener(runnable, executor);
}
#Override
public boolean cancel(boolean mayInterruptIfRunning) {
return _settableFuture.cancel(mayInterruptIfRunning);
}
#Override
public boolean isCancelled() {
return _settableFuture.isCancelled();
}
#Override
public boolean isDone() {
return _settableFuture.isDone();
}
#Override
public T get() throws InterruptedException, ExecutionException {
return _settableFuture.get();
}
#Override
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return _settableFuture.get(timeout, unit);
}
public void set(T value) {
_settableFuture.set(value);
}
public void setException(Throwable throwable) {
_settableFuture.setException(throwable);
}
// Resets the Future so that it can be provided to another call back
public void reset() {
_settableFuture = SettableFuture.create();
}
#Override
public void onDismiss(DialogInterface dialog) {
// Cancel the future here in case the user cancels our of the dialog
cancel(true);
super.onDismiss(dialog);
}
Using this class I'm able to create my own custom dialog fragments and use them like this:
ListenableDialogFragment<int> dialog = GetIdDialog.newInstance(provider.getIds());
Futures.addCallback(dialog, new FutureCallback<int>() {
#Override
public void onSuccess(int id) {
processId(id);
}
#Override
public void onFailure(Throwable throwable) {
if (throwable instanceof CancellationException) {
// Task was cancelled
}
processException(throwable);
}
});
This is where GetIdDialog is a custom instance of a ListenableDialogFragment. I can reuse this same dialog instance if needs be by simply calling dialog.reset in the onSuccess and onFailure methods to ensure that the internal Future gets reloaded for adding back to a callback.
I hope this helps you out.
Edit: Sorry forgot to add, in your dialog you can implement an on click listener that does something like this to trigger the future:
private class SingleChoiceListener implements DialogInterface.OnClickListener {
#Override
public void onClick(DialogInterface dialog, int item) {
int id = _ids[item];
// This call will trigger the future to fire
set(id);
dismiss();
}
}
I would maybe just using a static factory pattern of some variation to allow dynamic initialization of the DialogFragment.
private enum Operation {ADD, EDIT, DELETE}
private String title;
private Operation operation;
public static MyDialogFragment newInstance(String title, Operation operation)
{
MyDialogFragment dialogFragment = new DialogFragment();
dialogFragment.title = title; // Dynamic title
dialogFragment.operation = operation;
return dialogFragment;
}
Or.. and I would recommend this more, have a static factory method for each type of operation you will use it for. This allows different dynamic variations to be more concrete and ensures that everything works together. This also allows for informative constructors.
Eg.
public static MyDialogFragment newAddItemInstance(String title)
{
MyDialogFragment dialogFragment = new DialogFragment();
dialogFragment.title = title; // Dynamic title
return dialogFragment;
}
public static MyDialogFragment newEditItemInstance(String title)
{
MyDialogFragment dialogFragment = new DialogFragment();
dialogFragment.title = title; // Dynamic title
return dialogFragment;
}
And then of course create an interface that every calling Activity / Fragment (in which case you need to set this Fragment as the targetFragment and get reference to that target Fragment in your DialogFragment) so that the implementation is taken care of in the target Fragment and nothing to do with the DialogFragment.
Summary: There are various ways of going about this, for simplicity, I would stick with some form of static factory pattern and make clever use of interfaces to separate any the logic from the DialogFragment hence making it more reusable
EDIT: From your comment I would suggest you look at two things:
Target Fragments (See the comment I made on your question). You can invoke methods in your ListFragment from your DialogFragment.
Strategy Pattern. How does the Strategy Pattern work?. This allows you to perform the same operation (with various tailored implementation for each type) on different objects. Very useful pattern.

Categories

Resources