So I need to have access to a variable from MainActivty from another class. what's the best way to do so. Below is the scenario but I cannot call frag.receiveInt(give_this_int_to_fragment);
MainActivity.java:
import com.me.fragments.FragmentExtender
public class MainActivity{
int give_this_int_to_fragment;
protected void onCreate(...){
Fragment frag = new FragmentExtender();
give_this_int_to_frag = new int();
frag.receiveInt(give_this_int_to_frag);
}
}
FragmentExtender.java:
public class FragmentExtender extends Fragment{
int receive_int_from_main;
public View onCreateView(...){...}
receiveInt(int_from_main){
receive_int_from_main = int_from_main;
}
}
I'm not trying to create a duplicate variable, just a pointer to that variable in MainActivity if you catch my drift.
Create getter and setter for that variable in Activity
public class MainActivity{
int give_this_int_to_fragment;
protected void onCreate(...){
Fragment frag = new FragmentExtender();
}
}
public int getgive_this_int_to_fragment(){
return give_this_int_to_fragment;
}
public void getgive_this_int_to_fragment(int var){
give_this_int_to_fragment = var;
}
Now, in fragment you can use getActivity() to get activity context and then call getter
public class FragmentExtender extends Fragment{
public View onCreateView(...){
//....
int var = ((MainActivity) getActivity()).getgive_this_int_to_fragment();
}
}
The more elegant way will be to implement an interface in the Fragment and make the app inherit from it. That way you can comunicate that way.
interface FragmentInterface{
Object getMainValue();
void passValueToMain(Object obj);
}
With this code, you just have to add it to the MainActivity declaration and in the fragment constructor
public class MainActivity implements FragmentInterface{
int give_this_int_to_fragment;
protected void onCreate(...){
Fragment frag = new FragmentExtender();
....
}
}
And then in the Fragment
public class FragmentExtender extends Fragment{
private FragmentInterface mInterface;
int receive_int_from_main;
public View onCreateView(...){...}
#Override
public void onAttach(Context context) {
super.onAttach(context);
setListeners(context);
}
//This is for pre Marshmallow versions
#SuppressWarnings("deprecation")
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
setListeners(activity);
}
}
private void setListeners(Object object) {
if (object instanceof FragmentInterface) {
mListener = (FragmentInterface) object;
} else {
throw new RuntimeException(object.toString()
+ " must implement FragmentInterface");
}
}
}
This will work for any fragment and any activity that implement them
Related
I'm trying to adjust the observer pattern to my code, so in my case MSG0100 it's my Subject class that it updates the variable msg100PreselectionAplication, and the MainActivity class it's an concrete observer, and usually you have to create the Observer class, but my problem is that the MainActivity has to extend from that class and that's a problem because Java does not support multiple inheritance. Here is what i have until now, can some one give me an idea of what i need next? Please
MSG0100 class:
public class MSG0100 implements PreselectionAplicationUseCases {
private OnMsg100PreselectionChanged listener = null;
public void setOnMsgPreselectionChanged(OnMsg100PreselectionChanged listener) {
this.listener = listener;
}
public void setMsg100PreselectionAplication(boolean msg100PreselectionAplication) {
if(listener != null) {
listener.onPreselectionChanged(msg100PreselectionAplication);
}
}
}
interface OnMsg100PreselectionChanged {
void onPreselectionChanged(boolean isChanged);
}
Main activity class:
public class MainActivity extends AppCompatActivity {
private ExpandableListViewAdapter mExpandableListViewAdapter;
PreselectionAplicationUseCases preselectionAplicationUseCases;
public void Preselection(){
preselectionApplicationUseCases.setOnMsgPreselectionChanged(new OnMsg100PreselectionChanged {
#Override
void onPreselectionChanged(boolean isChanged) {
//do something with changed boolean
}
});
}
}
You should create Observer as an Interface which implemented by MainActivity like this:
interface Observer {
void update(Data data)
}
public class MainActivity extends AppCompatActivity implements Observer {
//…
#Override
public void update(Data data) {
// update your data to your UI here
}
//…
}
and modify your subject to receive observer
interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}
public class MSG0100 implements PreselectionAplicationUseCases, Subject {
private Data data = new Data();
private Observer o;
#Override
public void registerObserver(Observer o) {
this.o = o;
}
#Override
public void removeObserver(Observer o) {
o = null;
}
#Override
public void notifyObservers() {
o.update(data);
}
// ... other method that can update the data class
}
that is an Observer Pattern, but the way I see, you simply want to implement OnMsg100PreselectionChanged on Activity like:
public class MainActivity extends AppCompatActivity, OnMsg100PreselectionChanged {
void someMethod() {
MSG0100 msg0100 = new MSG0100();
msg0100.setOnMsgPreselectionChanged(this);
}
#Override
void onPreselectionChanged(boolean isChanged) {
}
}
I have already looked up many answers here about this issue but for the life of me I can't seem to fix this problem on my end and I need some help.
BasePresenter:
public abstract class BasePresenter<V> {
private V mView;
public void attachView(V view) { mView = view; }
public void detachView() { mView = null; }
}
BaseFragment:
public abstract class BaseFragment<P extends BasePresenter> extends Fragment {
#Inject protected P mPresenter;
#Override
public void onResume() {
super.onResume();
mPresenter.attachView(this); // unchecked call to 'attachView(V)' as a member of raw type 'BasePresenter'
}
#Override
public void onPause() {
super.onPause();
mPresenter.detachView();
}
}
MyPresenter:
public class MyPresenter extends BasePresenter<MyPresenter.MyView> {
#Inject
public MyPresenter() {}
public interface MyView {}
}
MyFragment:
public class MyFragment extends BaseFragment implements MyPresenter.MyView {}
The problem is in the type-variable declaration:
class BaseFragment<P extends BasePresenter>
BasePresenter is a generic class, so you need to specify what its type parameter is. From this snippet:
mPresenter.attachView(this);
It would seem that you expect BaseFragment to be bound to the type-variable V in BasePresenter - so I would rewrite your BaseFragment declaration as follows:
abstract class BaseFragment<P extends BasePresenter<BaseFragment<P>>> { ... }
That should take care of the unchecked warning. That said, I strongly suspect that what you are really after is something like this:
abstract class BaseFragment<P extends BasePresenter<V>, V> { ... }
Where V is an independent type-variable modelling the 'view'.
Simple, instead of
public abstract class BaseFragment<P extends BasePresenter> extends Fragment {
It should be
public abstract class BaseFragment<V, P extends BasePresenter<V>> extends Fragment {
or
public abstract class BaseFragment<P extends BasePresenter<BaseFragment<P>>> extends Fragment {
or
public abstract class BaseFragment<V extends BaseFragment<V, P>, P extends BasePresenter<V>> extends Fragment {
Basically, make sure the BasePresenter is parametrized with something.
EDIT:
Okay, based on what you're actually trying to do, you should do it like this:
public abstract class BasePresenter<V> {
private V mView;
public void attachView(V view) { mView = view; }
public void detachView() { mView = null; }
}
public abstract class BaseFragment<V extends BaseFragment<V, P>, P extends BasePresenter<V>> extends Fragment {
protected abstract P getPresenter();
#Override
public void onResume() {
super.onResume();
getPresenter().attachView(this); // unchecked call to 'attachView(V)' as a member of raw type 'BasePresenter'
}
#Override
public void onPause() {
super.onPause();
getPresenter().detachView();
}
}
public class MyPresenter extends BasePresenter<MyPresenter.MyView> {
#Inject
public MyPresenter() {}
public interface MyView {}
}
public class MyFragment extends BaseFragment<MyFragment, MyPresenter> implements MyPresenter.MyView {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
MyFragmentComponent component = ((MainActivity)getActivity()).getComponent().myFragmentComponent();
component.inject(this);
View view = inflater.inflate(R.layout.blah, container, false);
ButterKnife.bind(this, view);
return view;
}
}
EDIT2: Based on provided example:
public class RexTester {
// MAIN CLASS
static class Rextester {
public static void main(String args[]) {
new MyFragment();
}
}
// MVP CODE
interface BaseView {}
final static class MyPresenter extends BasePresenter<MyPresenter.MyView> {
public MyPresenter() {}
public void executeAction() {
mView.onCallback();
}
interface MyView extends BaseView {
void onCallback();
}
}
abstract static class BasePresenter<V extends BaseView> {
protected V mView;
public void attachView(V view) { mView = view;}
public void detachView() { mView = null; }
}
final static class MyFragment extends BaseFragment<MyPresenter.MyView, MyPresenter> implements MyPresenter.MyView {
private MyPresenter mPresenter;
public MyFragment() {
mPresenter = new MyPresenter();
onResume(); // Mock onResume() lifecycle event!
mPresenter.executeAction();
onPause(); // Mock onPause() lifecycle event!
}
protected MyPresenter getPresenter() {
return mPresenter;
}
#Override
protected MyPresenter.MyView getThis() {
return this;
}
public void onCallback() {
System.out.println("Hello AndroidMVP!");
}
}
abstract static class BaseFragment<V extends BaseView, P extends BasePresenter<V>> extends Fragment implements BaseView {
protected abstract P getPresenter();
protected void onResume() {
super.onResume();
getPresenter().attachView(getThis());
}
protected abstract V getThis();
protected void onPause() {
super.onPause();
getPresenter().detachView();
}
}
// ANDROID FRAMEWORK MOCK
abstract static class Fragment {
protected void onResume() {}
protected void onPause() {}
}
}
So my ListFragment is Tab2 and it looks something like this.
public class Tab2 extends ListFragment {
public interface MyFragmentListener {
public void onFragmentItemSelected(String CheckSwitch);
}
static MyFragmentListener myListener;
public static void setMyFragmentListener(MyFragmentListener listener) {
myListener = listener;
}
on some condition
if (TempTweet < CheckingTemp)
{
myListener.onFragmentItemSelected("TurnOn");
}
on Tab1
public class Tab1 extends Fragment implements Tab2.MyFragmentListener {
#Override
public void onFragmentItemSelected(String CheckSwitch) {
if(CheckSwitch.equals("TurnOn"))
{
//Some Actions
}
}
on MainActivity
Tab2.setMyFragmentListener(Tab1);
This answer has been taken from Passing value from ListFragment to another ListFragment now i am very new to Java and android so i am not sure it always says "Expression Expected"
You can make global static variable so that you can use it wherever you want.
I have a fragments that builds a songs ArrayList, i want to pass that ArrayList to the framgment's activity . I know i can use interface, but not sure how i could do it
public class SongsListFragment extends Fragment
{
public interface passArrayList {
public void onArticleSelected(Uri articleUri);
// from android guide i don't know what to do
}
}
Here is what i have so far, please let me know why im getting NullPointer
on MainActivity
#Override
public void onFragmentSetSongs(ArrayList<Song> songs){
songsArrayList = songs;
}
#Override
public void onSongListItemClick(int position) {
musicService.setSong(position);
Song playSong = songsArrayList.get(position);
txtCurrentSongTitle.setText(playSong.getTitle());
txtCurrentSongTitle.requestFocus();
musicService.playSong();
btnPlayPause.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_pause));
if (playbackPaused) {
playbackPaused = false;
}
//setDownloaded();
}
on Fragment
OnFragmentInteractionListener songsCallBack;
OnFragmentInteractionListener songsItemClick;
public interface OnFragmentInteractionListener {
public void onFragmentSetSongs(ArrayList<Song> s);
public void onSongListItemClick(int position);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
songsCallBack = (OnFragmentInteractionListener) getActivity();
songsItemClick = (OnFragmentInteractionListener) getActivity();
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
#Override
public void onDetach() {
super.onDetach();
songsCallBack = null;
songsItemClick= null;
}
listView = (ListView) root.findViewById(R.id.listViewSongs);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
songsItemClick.onSongListItemClick(position);
}
});
on the method where i finish building the songArrayList, i did
songsCallBack.onFragmentSetSongs(songArrayList);
Error When i Click on ListView
at com..activities.MainActivity.onSongListItemClick(MainActivity.java:107)
at com..fragments.SongsListFragment$1.onItemClick(SongsListFragment.java:194)
at android.widget.AdapterView.performItemClick(AdapterView.java:308)
at android.widget.AbsListView.performItemClick(AbsListView.java:1478)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:3480)
Error Position
musicService.setSong(position); //Main Activity (MainActivity.java:107)
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
songsItemClick.onSongListItemClick(position); < -- here
}
Change name of your interface so that it begins from capital letter. Then in your activity add this line to declaration of your activity: public class FragmentActivity extends Activity implements PassArrayList, override interface method. And in fragment add following:
PassArrayList mCallback;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mCallback = (PassArrayList) getActivity();
}
#Override
public void onDetach() {
super.onDetach();
mCallback = null;
}
And somewhere in your code, when you want to pass your list of songs back to the activity call the method onArticleSelected() on your mCallback object and pass to this method your arraylist. Then this arraylist will come as an argument to the method onArticleSelected() in your activity and you could make with it anything that you like. But don't forget to nullify link to mCallback in onDetach() hook method to prevent context leak
The title may be bit confusing but here is what I am facing
I have a class:
public abstract class BaseFragmentActivity<T> extends FragmentActivity {
static final int PROGRESS_DIALOG = 0;
Dialog progessDialog;
public abstract void displayData(T output);
#Override
protected Dialog onCreateDialog(int id) {
if (id == PROGRESS_DIALOG) {
ProgressDialog progressDialog = ProgressDialog.show(this, "",
"Loading. Please wait...", true);
progessDialog = progressDialog;
}
return progessDialog;
}
class PerformOPTask extends AsyncTask<Void, String, T> {
// connector=new JSONConnector();
Connector connector;
String curUrl;
Class<T> clazz;
PerformOPTask(String url, Class<T> curClazz) {
//connector = new UnitTestConnector();
connector = new JSONConnector();
curUrl = url;
clazz = curClazz;
}
#Override
protected T doInBackground(Void... params) {
return connector.getData(URLUtils.getFormattedUrl(curUrl),clazz);
}
#Override
protected void onPostExecute(T output) {
displayData(output);
}
}
}
Then I have a subclass as :
public abstract class BaseListFragmentActivity<T> extends BaseFragmentActivity<T> implements OnItemClickListener, OnClickListener{
protected ListView mList;
/** Called when the activity is first created. */
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.table_list);
CommonUtil.getActionBarWithBackButton(this,getLayoutInflater());
mList=(ListView)findViewById(R.id.table_list_listView);
mList.setOnItemClickListener(this);
}
public void onBackABButtonPressed(View view) {
finish();
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
#Override
public abstract void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3);
}
Now I am extending this class as below:
public class ListAccountsActivity<T> extends BaseListFragmentActivity<AccountData> {
protected Acct[] mItems;
private String[] mIcons;
protected boolean displayHandledBySubClass=false;
/** Called when the activity is first created. */
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
new PerformOPTask(getString(R.string.get_account),AccountData.class).execute();
showDialog(PROGRESS_DIALOG);
//.getData(URLUtils.getFormattedUrl(getString(R.string.get_account)),actData);
}
#Override
public void onItemClick(AdapterView<?> lv, View view, int position, long id) {
// super.onListItemClick(l, v, position, id);
// Get the item that was clicked
Acct account = (Acct) mList.getAdapter().getItem(position);
Intent intent=new Intent(this,AccountDetailViewActivity.class);
intent.putExtra("selectedAccount",account);
startActivity(intent);
}
#Override
public void displayData(AccountData output){
if(displayHandledBySubClass){
//handle display in subclass
handleDisplayData(output);
}
else {
Acct[] accountArray = new Acct[output.getAccount().size()];
mItems = output.getAccount().toArray(accountArray);
IWMArrayAdapter<Acct> adapter = new IWMArrayAdapter<Acct>(this, mItems);
adapter.setIcons(mIcons);
adapter.setArrowNeeded();
//mList is superClassVariable
mList.setAdapter(adapter);
dismissDialog(PROGRESS_DIALOG);
adapter.notifyDataSetChanged();
}
}
public void handleDisplayData(T output){
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
//Toast.makeText(this, "Tapped search", Toast.LENGTH_SHORT).show();
super.onCreateOptionsMenu(menu);
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.list_servers_menu, menu);
// Calling super after populating the menu is necessary here to ensure
// that the
// action bar helpers have a chance to handle this event.
return true;
}
}
My Question is can I make handleDisplayData generic in some way so that I can pass any type to it. What I am trying to do is to reuse logic in BaseListFragmentActivity as much as possible and handle the only task specific to ListAccountsActivity or its subclass in that class/subclass.
I hope my question is clear, Thanks for any help
If I understand correctly, you want to be able to use type-specific methods from the base in the subclass, and for that you need to make everything generic:
public abstract class GenericBase<T> { ... }
public abstract class ExtendedGeneric<T> extends GenericBase<T> { ... }
public class ExtendedGenericSub<T> extends ExtendedGeneric<T> { ... }
Point being that if ExtendedGeneric extends GenericBase<DataOutput>, only methods of GenericBase<DataOutput> are accessible from ExtendedGeneric.
Is this what you want?
public abstract class ExtendedGeneric<C> extends GenericBase<DataOutput> {
boolean handleInSub;
#Override
public void displayData(DataOutput t) {
if(handleInSub){
handleInSubClass(getValue(t));
}
//handle here
System.out.println(t);
}
protected abstract void handleInSubClass(C c);
protected abstract C getValue(DataOutput t);
}
This is of course only assumes that the data type C will come from DataOutput t. The idea is you can also make the ExtendenGeneric parameterized so you can make the classes extending it controls the datatype supplied to handleInSubClass.
Sure you can:
GenericParent
public abstract class GenericParent<T> {
public abstract void displayData(T t);
}
GenericChild
public class GenericChild<T> extends GenericParent<GenericChild> {
#Override
public void displayData(GenericChild t) {
// Do Something Here...
}
/**
* Using protected better than public,
* to prevent other class access directly to this method.
* But make sure this the other class is not same package with this GenericChild,
* because if it same package than the other class can access directly this method.
**/
protected void handleSubClass(T t){}
}
SubClass
public class SubClass extends GenericChild<SubClass> {
#Override
public void handleSubClass(SubClass t){
// Do Something Here...
}
}
Are we talking about this kind of thing?
class Vehicle {};
abstract class RoadVehicle extends Vehicle {
abstract int getNumberOfWheels();
}
class Truck extends RoadVehicle {
int getNumberOfWheels() {
return 8;
}
}
class Car extends RoadVehicle {
int getNumberOfWheels() {
return 4;
}
}
abstract class GenericHandler<T extends Vehicle> {
public abstract void displayData(T t);
}
abstract class RoadVehicleHandler<T extends RoadVehicle>
extends GenericHandler<T> {
public void displayData(T t) {
System.out.println(t.getNumberOfWheels() + " wheels");
specialStuff();
}
abstract void specialStuff();
}
class CarHandler extends RoadVehicleHandler<Car> {
void specialStuff() { /* honk horn */ }
}
class TruckHandler extends RoadVehicleHandler<Truck> {
void specialStuff() { /* flash lights */ }
}