Java hierarchy inside an android listner - java

In my android application I want to solve the following scenario.
class Login extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutBuilder objLB=new LayoutBuilder(this);
objLB.createSpinner();
}
public void spinnerItemSelectedEvent(AdapterView<?> parent, View view,
int pos, long id)
{
}
}
class LayoutBuilder {
private Activity objActivity;
public LayoutBuilder(Activity a) {
objActivity = a;
}
public void createSpinner() {
final Spinner objSPItem = new Spinner(objActivity);
objSPItem.setOnItemSelectedListener(
new Spinner.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id)
{
// Do some common activity
objActivity.spinnerItemSelectedEvent(parent,view,pos,id);
// calling this for do some additional task
}
public void onNothingSelected(AdapterView<?> arg0) {}
});
objActivity.spinnerItemSelectedEvent()
}
}
and the problem is when i try to access spinnerItemSelectedEvent(parent,view,pos,id) from the 'onItemSelected' listner inside createSpinner method
I got the following error.
The method spinnerItemSelectedListener(AdapterView, View, int, long) is undefined for the type Activity
but out side the listner the access to the method works ok(neglect parameter list). What is the reason behind that? is any alternate way exist for solving this? plz help

Activity in android represents a screen. You are making a variable objActivity of type Activity whereas it should be of type Login where the function spinnerItemSelectedEvent() is declared. Change the following lines:
private Activity objActivity;
to
private Login objActivity;
and your code should run.
EDIT
Have a BaseActivity and let all your other activities extend this BaseActivity. To make the function spinnerItemSelectedEvent() reusable declare it in the BaseActivity and you can use it the way you are trying to do it now.
Example:
class BaseActivity extends Activity{
public void spinnerItemSelectedEvent(AdapterView<?> parent, View view,
int pos, long id){ }
}
class Login extends BaseActivity{
public void spinnerItemSelectedEvent(AdapterView<?> parent, View view,
int pos, long id){ //Local implementation of the function}
}
class LayoutBuilder {
private BaseActivity objActivity;
}

The problem is that inside LayoutBuilder, you have declared objActivity to be an Activity. Declare it to be a Login and all should be fine:
class LayoutBuilder {
private Login objActivity;
public LayoutBuilder(Login a) {
objActivity = a;
}
. . .
EDIT
If you want your LayoutBuilder class to be reusable by other activities, then one way to do this is via an interface declaration. For instance:
public interface SpinnerSelectionHandler {
void spinnerItemSelectedEvent(AdapterView<?> parent, View view,
int pos, long id);
}
Then declare Login as:
public class Login extends Activity implements SpinnerSelectionHandler {
. . .
Finally, redefine LayoutBuilder to take a SpinnerSelectionHandler in its constructor:
class LayoutBuilder {
private Activity objActivity;
private SpinnerSelectionHandler selectHandler;
public LayoutBuilder(Activity a, SpinnerSelectionHandler handler) {
objActivity = a;
selectHandler = handler;
}
And then replace
objActivity.spinnerItemSelectedEvent(parent,view,pos,id);
with
spinnerHandler.spinnerItemSelectedEvent(parent,view,pos,id);
Plus, if you don't need the Activity reference for anything else, you can get rid of it from the LayoutBuilder class.

Related

How to pass data from activity to a class?

How can i send data from an activity to a class ?
I tried to pass a String using getter but this gives me the initial value of the variable , but my String's value changes in my onCreate. Any ideas how can i pass it to my class ?
Here is some code :
public class MainActivity extends AppCompatActivity {
private String global ;
public String getGlobal() {
return global;
}
...
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
global = String.valueOf(parent.getItemAtPosition(position));
}
});
}
And here is my class
public class SimpleVar {
MainActivity mainActivity = new MainActivity() ;
String data = mainActivity.getGlobal; }
Any help will be much appreciated. Thank you in advance !
global is not actually "global"
Each instance of the Activity has its own string, and the OS can decide to kill your Activity at any time and recreate it, so therefore don't rely on a variable from an Activity within another class.
Secondly, never ever make a new Activity. That is no longer tied to the Activity that you would eventually click the button on.
It's hard to determine what you really need, but this is more correct.
public class SimpleVar {
String data;
}
With the Activity sending data to it
private SimpleVar var;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
var = new SimpleVar();
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
var.data = String.valueOf(parent.getItemAtPosition(position));
}
});
}
If you need that object elsewhere, you need to pass it around to those classes from this Activity
try to make constructor for your class
public class SimpleVar {
private String data;
public SimpleVar(String data) {
this.data = data;
}
public void setData(String data) {
this.data = data;
}
}
then in your activity new the class and then set data to it
You should not create new mainactivity in your class.
When on instantiating the class pass to it a reference to Activity in which the class was created. Reference to Activity should be kept in a weakreference. Then You can make a getter in the Activity and call it from Your class.
Or You can do the opposite - keep reference to the instantiated object in the Activity. Use setter from the activity to pass new values to the object.

How to set the title of Android toolbar from another class?

I would like to do something like this:
if (total != 0) {
percentage = String.valueOf((count * 100) / total);
Log.e("Percentage", percentage);
myActivity.getSupportActionBar().setTitle("Progress: " + percentage + "%.");
}
However, I can't call getSupportActionBar() because it says Non-static method 'getSupportActionBar()' cannot be referenced from a static context. How can I solve this?
Update
This is the method inside my public class where I'd like to call the above code;
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
}
});
}
Casting your activity can resolve your problem. Suppose your Activity Name is YourCustomActivity. Now cast the Activity like below. Hope it will work.
YourCustomActivity activity=(YourCustomActivity)myActivity;
activity.getSupportActionBar().setTitle("");
Please Let me know if it works or not.
You can pass activity parameter to another class and use activities funcitons like below;
public class CityModel {
Activity activity;
public CityModel(Activity activity) {
this.activity = activity;
}
private void doIt() {
((YourActivity) activity).changeTitle("New Title");
}
}
And define this class instance like below;
public class YourActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CityModel model = new CityModel(this); // this-> Your activity.
}
public void changeTitle(String newTitle){
getSupportActionBar().setTitle(newTitle);
}
}
Hope it helps.
Thanks to other answers, but none of them fit what I wanted.
I solved it by moving the code to the activity in question and setting the title from there. However, the main change was to post the percentage value from a listener method, in my case: onItemCheckBoxChecked. This meant that every time a user checked a box (could be other listeners in case of a textview or something else) the percentage was calculated in real time. I also made the percentage variable public.
Because getSupportActionBar() is not static method. If you are using this method in static class or static method then you will get below error.
Non-static method getSupportActionBar() cannot be referenced from a static context
If you want to common method for it you can make one think create public method in your activity and call in your fragments.
public void setToolBar(String title) {
getSupportActionBar().setTitle(title);
}
If you have Activity, simply you can call below code.
getSupportActionBar().setTitle(title);
Edit My Code :
public static void setToolbar(final AppCompatActivity activity,String title){
activity.getSupportActionBar().setTitle(title);
}
Edit Code :
My RecyclerViewAdapter class :
public class ExploreGalleryAdapter extends RecyclerView.Adapter<ExploreGalleryAdapter.ViewHolder> {
private AppCompatActivity activity;
private ArrayList<ExploreGalleryModel> exploreGalleryModelArrayList;
// private String status;
public ExploreGalleryAdapter(AppCompatActivity activity, final ArrayList<ExploreGalleryModel> exploreGalleryModelArrayList, final String status) {
this.activity = activity;
this.exploreGalleryModelArrayList = exploreGalleryModelArrayList;
// this.status = status;
}
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
activity.getSupportActionBar().setTitle(title);
}
});
}

method call from adapter class to activity

Adapter:
check_list_item.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
JPrequirements.prepareSelection(v, getAdapterPosition());
}
});
JPrequirements is the activity. and prepareSelection is non-static method inside activity. I cannot access it from adapter.
ERROR:
non static method cannot be referenced from a static context
Which is right. that's why I tried with:
JPrequirements().prepareSelection(v, getAdapterPosition()); // Creating an instance...
But, the problem is I lost all activity component here. eg. layout components and other supporting variables. I don't want that. What is the best way to deal with this? How can I get updated value from adapter to activity? So, I can display it real-time.
Thanks.
You can achieve this via interface. Firstly, define an interface class as:
public interface ActivityAdapterInterface {
public void prepareSelection(View v, int position);
}
Now, implement the interface in your Activity as:
public class JPrequirements extends AppCompatActivity implements ActivityAdapterInterface {
...
public void prepareSelection(View v, int position) {
// cool stuff here
}
...
}
Make sure you pass this interface reference to your Adapter via its constructor. Then finally call it on click as:
check_list_item.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mActivityAdapterInterface.prepareSelection(v, getAdapterPosition());
}
});
[EDIT]
To provide the interface to your Adapter provide it the constructor.
public class YourAdapter ... {
private ActivityAdapterInterface mActivityAdapterInterface;
public YourAdapter(..., ActivityAdapterInterface activityAdapterInterface) {
activityAdapterInterface = mActivityAdapterInterface;
}
}

Communicate from Activity to Fragment using Interface

I have searched SO for this problem but was not able to find anything which would solve my problem. My problem is, I have a activity which contains FrameLayout which is constantly updated with different fragments. The top view and bottom view are going to remain same hence they are in the layout of the
activity.
As you can see bottom view has a button on click of that i want to make changes in the fragments which will be present in the FrameLayout.
I have created a interface
public interface ShowFormula {
void showFormula(boolean show);
}
which i will use to implement in the fragment.
Now the main problem in my MainActivity class i am trying to initialize the interface but not able to as i am getting class cast exception
showFormula = (ShowFormula) this;//yes i know this is wrong
How should i initialize this in order to communicate with the fragment.
Main goal is to toggle the view in fragments on click of the button in activity.
Thanks in advance.
You don't need to use an interface to make calls from an Activity to a Fragment. Just keep a reference to the current Fragment, and call into a public method in the Fragment from the Activity.
If you have multiple Fragments and you don't want to keep a reference for each one, you can create a Fragment base class, declare the common method in the base class, and then implement that method override in all of your Fragments that inherit from the base Fragment. Then, keep one reference of the base Fragment type, and always have it set to the Fragment that is shown currently.
Activity ---> Fragment
Communication from Activity to Fragment is pretty straightforward. You
really don't need a listener.
Let's say you have a method inside Fragment share()
public class MyFragment extends Fragment{
public static MyFragment getInstance()
{
return new MyFragment();
}
........
public void share()
{
// do something
}
}
How to call share() method from an Activity?
Get the reference of the Fragment and call the method. Simple!
MyFragment myFragment = MyFragment.getInstance();
myFragment.share();
You can see the full working code for Fragment to Fragment Communication
Just to add to Daniel Nugent's brilliant answer, here are snippets from my working code for delegating calls from Activity to Fragment.
I have a MVP architecture and I have defined the error handling method showError on the BaseView class and the code below demonstrates how to handle the UI on a TargetFragment class. I, specifically needed to hide my progress spinner on the fragment upon any error scenario. Here's the code snippets for the base classes:
public interface BaseView {
void showError(ErrorResponse errorResponse);
}
public abstract class BaseActivity implements BaseView {
#Override
public void showError(ErrorResponse errorResponse) {
// Check error condition or whatever
// ...
MaterialDialog dialog = new MaterialDialog.Builder(this)
.title(R.string.dialog_error_title)
.content(R.string.error_no_internet)
.positiveText(R.string.dialog_action_ok)
.build();
dialog.show();
}
}
public abstract class BaseFragment implements BaseView {
#Override
public void showError(ErrorResponse errorResponse) {
((BaseView) getActivity()).showError(errorResponse);
}
}
And, this is how I handle UI inside my TargetFragment class:
public final class TargetFragment extends BaseFragment implements TargetView {
#Override
public void showError(ErrorResponse errorResponse) {
super.showError(errorResponse);
hideSpinner();
// Do other UI stuff
// ...
}
private void hideSpinner() {
spinner.setVisibility(View.INVISIBLE);
}
}
a clean solution:
public interface ShowFormula {
public void showFormula(boolean show);
}
public class MyActivity implements ShowFormula {
...
#Override
public void showFormula(boolean show) {
/** Your Code **/
}
...
}
public class MyFragment {
private ShowFormula listener;
...
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
listener = (ShowFormula) activity;
// listener.showFormula(show?);
} catch (ClassCastException castException) {
/** The activity does not implement the listener. **/
}
}
...
}
simple thing make public method in fragments then call it on from your activity.
e.g
MyFragment fragment = new MyFragment();
fragment.doSomeThing();
doSomeThing() is a public method in MyFragment.
Activity to Fragment Communication via Interface:
public class MyActivity {
private ShowFormula showFormulaListener;
public interface ShowFormula {
public void showFormula(boolean show);
}
public void setListener(MyFragment myFragment) {
try {
showFormulaListener = myFragment;
} catch(ClassCastException e) {
}
}
}
public class MyFragment implements ShowFormula{
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
((MyActivity) activity).setListener(this);
} catch (ClassCastException e) {
Log.e(TAG, e.toString());
}
}
#Override
public void showFormula(boolean show) {
/** Your Code **/
}
}
Once you are done setting this, you can call 'showFormulaListener.showFormula(boolVal)'

Run non static method on current activity from another class

I am struggling to figure out how to simply call and run a method from a class (that is not an activity) on my current activity.
my current code:
CustomListViewAdapter.java (other class)
public void onClick(View v) {
int position = Photos.listView.getPositionForView(v);
Log.v("value ", "tada" + position);
Photos photos = new Photos();
photos.deletePhoto(position);
}
});
Photos.java (my current activity class)
public void deletePhoto(int pos){
Toast.makeText(thisActivity, "delete index:"+pos , Toast.LENGTH_SHORT).show();
mylist.remove(pos);
setupListView();
}
Problem is, this way of doing it makes a new instance of mylist which gives me a outofbounds error. How can I do this correctly so I get the current activity and update it accordingly?
If you don't want a static method, you could create in interface.
public interface DeleteInterface {
public void deletePhoto(int position);
}
And then in your adapter's constructor...
private DeleteInterface mInterface;
public CustomListAdapter(/* other paramaters */ DeleteInterface interface) {
// other assignments
mInterface = interface;
}
And then in your Activity...
public class Photos extends Activity implements DeleteInterface {
// your code here
public void deletePhoto(int pos) {
// your method here
}
}
But make sure that when you create your Adapter, you have a pointer to the current Activity and pass it through the Adapter's constructor.
Last but not least...
In your adapter, call mInterface.deletePhoto(position); to call your Activity's method.

Categories