I am trying to pass a simple String from #EActivity to #EFragment , so i can later on assign that value to textView in #EFragment , I don't want to use saving in bundle pattern
My attempt:
#EActivity(R.layout.activity_pre_plan_detail)
public class PrePlanDetailActivity extends AppCompatActivity {
// some long adapter code
#AfterViews
void inits_(){
adapter.addFragment( myFragment_.builder().build().setme("something"));
}
}
______________________________________________________________________________
#EFragment(R.layout.fragment1)
public class PlanDescription extends Fragment {
#ViewById
TextView tv_fpd_description;
public void setme(String data){
tv_fpd_description.setText(data);
}
}
output/error:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
Note: All mentioned annotations are part of boilerplate library [android annotation][1]
Try with local broadcast manager
**Activity code:**
-----------------
Intent intent = new Intent("my-custom-event");
intent.putExtra("message", "something");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
**fragment code:**
-------------------
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(onReceiver , new IntentFilter("my-custom-event"));
}
#Override
public void onDestroy() {
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(onReceiver );
super.onDestroy();
}
**BroadCastReceiver:**
private BroadcastReceiver onReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String data= intent.getStringExtra("message");
tv_fpd_description.setText(data);
}
};
You should really use a Fragment argument for this:
#EFragment(R.layout.fragment1)
public class PlanDescription extends Fragment {
#FragmentArg
String someDescription;
#ViewById
TextView tv_fpd_description;
#AfterViews
void afterViews() {
tv_fpd_description.setText(someDescription);
}
}
And you can create the Fragment like this:
PlanDescription_.builder().
someDescription("your data")
.build();
Related
I have the MainActivity that a want to communicate with a class using an interface.
public interface MyInterface(){
public void doAction();
}
In my MainActivity I will have this piece of code:
public class MainActivity extends AppCompatActivity implements MyInterface(){
//....some more code here
#Override
public void doAction() {
//any code action here
}
//....some more code here
}
So now, If I have another class (NOT ACTIVITY), how should I correctly make the link between class---interface---mainActivity??
public class ClassB {
private MyInterface myinterface;
//........
//...... how to initialize the interface
}
I am confused about how to initialize and use the interface in ClassB
In the constructor of other class: ClassB, accept interface as argument and pass reference of Activity, hold that object in your Activity.
like so:
public class MainActivity extends AppCompatActivity implements MyInterface()
{
private ClassB ref; // Hold reference of ClassB directly in your activity or use another interface(would be a bit of an overkill)
#Override
public void onCreate (Bundle savedInstanceState) {
// call to super and other stuff....
ref = new ClassB(this); // pass in your activity reference to the ClassB constructor!
}
#Override
public void doAction () {
// any code action here
}
}
public class ClassB
{
private MyInterface myinterface;
public ClassB(MyInterface interface)
{
myinterface = interface ;
}
// Ideally, your interface should be declared inside ClassB.
public interface MyInterface
{
// interface methods
}
}
FYI, this is also how View and Presenter classes interact in MVP design pattern.
public class MainActivity extends AppCompatActivity implements
MyInterface
{
OnCreate()
{
ClassB classB= new ClassB(this);
}
}
public class ClassB
{
private MyInterface myinterface;
public ClassB(MyInterface myinterface)
{
this.myinterface=myinterface;
}
void anyEvent() // like user click
{
myinterface.doAction();
}
}
public class MainActivity extends AppCompatActivity implements MyInterface(){
private ClassB ref;
#Override
public void onCreate (Bundle savedInstanceState) {
ref = new ClassB();
ref.setMyinterface(this);
}
#Override
public void doAction () {
// any code action here
}
}
public class ClassB{
private MyInterface myinterface;
public setMyInterface(MyInterface interface){
myinterfece = interface;
}
public interface MyInterface{
// interface methods
}
}
//-------------------------------------
//Two way communication using Interface
//-------------------------------------
//A. Interfaces
//Communicator Interface ( Activity to Fragment )
public interface CommunicateToFragment {
public void CallBack(String name);
}
// Communicator Interface ( Fragment to Main )
public interface CommunicateToMain {
public void respond(String data);
}
//B. Main Class implements CommunicateToMain Interface
//Use CommunicateToFragment interface to send data in FragmentA
public class MainActivity extends AppCompatActivity implements CommunicateToMain {
private CommunicateToFragment communicateToFragment;
public void setCommunicateToFragment(CommunicateToFragment communicateToFragment) {
this.communicateToFragment = communicateToFragment;
}
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void respond (String data) {
communicateToFragment.CallBack("Callbacked when onCreate method Created" + data);
Log.d("test","get result from fragment: " + data);
FragmentManager manager = getFragmentManager();
FragmentB f2 = (FragmentB) manager.findFragmentById(R.id.id_fragment2);
f2.changeText(data);
}
}
//C. FragmentA implements CommunicateToFragment
//Use CommunicateToMain interface to send data in MainActivity
public class FragmentA extends Fragment implements View.OnClickListener, CommunicateToFragment{
Button button;
int counter=0;
CommunicateToMain commToMain;
#Nullable
#Override
public View onCreateView (LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_a,container,false);
}
#Override
public void onActivityCreated (#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
commToMain = (CommunicateToMain) getActivity();
button = getActivity().findViewById(R.id.button);
button.setOnClickListener(this);
if(getActivity() instanceof MainActivity){
((MainActivity) getActivity()).setCommunicateToFragment(this);
}
}
#Override
public void onClick (View view) {
counter++;
commToMain.respond("The button was clicked" + counter + " Times");
}
#Override
public void CallBack(String name) {
Log.d("test","get result from main activity: " + name);
}
}
How can i make a callback to an Activity form a Java Class?
Example:
public class TestClass{
String text = "Test";
public TestClass(Context context){
startActivity(new Intent(context, SomeActivity.class));
}
private void sendToSomeActivity(){
//Call some method of SomeActivity and pas text as string
}
}
When sendToSomeActivity() is called, i want to make a callback to the already started SomeActivity and pass some text to the Activity. In SomeActivity i want to use the text.
Note: The TestClass object that i want to use is already created in another class.
How can this be done?
The solution I chose is as follows:
Use BroadcastReceivers to communicate between Java classes and Activities.
Example:
public class SomeActivity extends Activity{
private MyBroadcastReceiver receiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
receiver = new MyBroadcastReceiver();
this.registerReceiver(receiver, new IntentFilter(MyBroadcastReceiver.ACTION));
}
#Override
public void onDestroy() {
super.onDestroy();
this.unregisterReceiver(receiver);
}
private class MyBroadcastReceiver extends BroadcastReceiver{
public static final String ACTION = "com.example.ACTION_SOMETHING"
#Override
public void onReceive(Context context, Intent intent) {
String test = intent.getStringExtra("dataToPass");
}
}
}
public class TestClass{
private String test = "TEST";
private Context context;
public TestClass(Context context){
this.context = context;
}
private void sendToSomeActivity(){
Intent intent = new Intent();
intent.setAction(SomeActivity.MyBroadcastReceiver.ACTION);
intent.putExtra("dataToPass", test);
context.sendBroadcast(intent);
}
}
Try this..
public class TestClass{
interface Implementable{
public void passData(String text);
}
Implementable imple;
String text = "Test";
public TestClass(Context context){
startActivity(new Intent(context, SomeActivity.class));
}
private void sendToSomeActivity(){
if(imple != null){
imple.passData(text);
}
}
public void setListener(Implementable im){
imple = im;
}
}
class SomeActivity implements Implementable{
new TestClass().setListener(this);
#override
public void passData(String text){
//here is your text
}
}
In your java class create an interface like this
public class TestClass{
private MyInterface myInterface;
public interface OnSendSomething {
public void onSending(String sendWhateverYouWant);
}
public void setOnSendListener(MyInterface myInterface) {
this.myInterface = myInterface;
}
}
private void sendToSomeActivity(){
//Call some method of SomeActivity and pas text as string
myInterface.onSending(sendWhateverYouWant);
}
And in your activity do something like this:
TestClass tclass = new TestClass(context);
tclass.setOnSendListener(new OnSendSomething () {
#Override
public void onSending(String sendWhateverYouWant) {
//sendWhateverYouWant is here in activity
}
});
You can also visit these links for better understanding.
How to create our own Listener interface in android?
Observer Design Pattern in Java
I need to transmit data from my activity layer to a view (or at least its fragment) that is not a child of AdapterView.
For a ListView, I could do this very easily with its adapter, but I am stuck on how to reproduce this behavior for a non AdapterView widget (for clarity, let's say a TextView).
I don't want to keep a reference to my fragment (or worse, the view) at Activity level.
Any ideas ?
One way to do this is to use java.util.Observable/Observer :
import java.util.Observable;
import java.util.Observer;
public class MyTextView extends View implements Observer{
#Override
public void update(Observable observable, Object data) {
this.setText((String)data);
}
}
Then, you need an Observable class :
import java.util.Observable;
public class MyObservable extends Observable {
public void setText(String text){
notifyObservers(text);
}
}
Activity :
public class MainActivity extends Activity {
TextView tv;
#Override
public void onCreate(Bundle savedInstanceState) {
...
MyObservable mtv = new MyTextView(getApplicationContext());
MyTextViewModel mm = new MyTextViewModel(10);
mm.addObserver(mtv);
mm.setText("test");
// demonstrated in an activity to shorten the sample, but ideally you would
// keep the observer at activity level and manage the view in the fragment
}
}
------------------------------------------------
Another way to do this is through android.database.DataSetObservable to implement a more traditional Adapter like object :
public class CustomAdapter extends DataSetObservable {
String mText;
public String getText() {
return mText;
}
public void setText(String text) {
mText = text;
}
}
You manipulate it like any other adapter at Activity level :
public class MyActivity extends Activity {
private CustomAdapter mCustomAdapter;
#Override
protected void onCreate() {
...
mCustomAdapter = new CustomAdapter();
}
private void initializeFragment (Fragment fragment) {
// this or whatever method you use to setup your fragments
((MyFragment) fragment).setCustomAdapter(mCustomAdapter);
}
private void onDataLoaded (Stg data) {
// callback method invoked when the network thread has finished loading data
mCustomAdapter.setText(data.text);
mCustomAdapter.notifyChanged();
}
Finally, the only thing missing is the link between your fragment and the view :
public class MyFragment extends Fragment {
private CustomAdapter mCustomAdapter;
public setCustomAdapter(CustomAdapter adapter) {
// this method allows to setup the adapter at startup
mCustomAdapter = adapter;
}
protected DataSetObserver mMyViewObserver = new MyObserver();
private class MyObserver extends DataSetObserver {
#Override
public void onChanged() {
mUpdateHandler.sendEmptyMessage(0);
}
}
private Handler mUpdateHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
updateMyView();
}
};
private void updateMyView() {
if (mView == null) {
return;
}
mView.setMainTextViewText(mCustomAdapter.getText());
}
}
And here you have it. Each time you call notifyChanged(), your observer gets called. In return, he invokes the handler that update the view.
Here you have it, leak free, thread safe custom adapter for any kind of view.
I have an Activity and non Activity class. How to call a method in Activity class from non Activity class
public class MainActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
DataClass dc = new DataClass();
dc.show();
}
public void call(ArrayList<String> arr) {
// Some code...
}
}
public class DataClass {
public void show(ArrayList<String> array) {
// Here I want to send this ArrayList values into the call
// method in activity class.
MainActivity act = new MainActivity();
act.call(array);
}
}
Just create a callback interface inside the DateClass.
public DateClass {
public interface IDateCallback {
void call(ArrayList<String> arr);
}
private IDateCallback callerActivity;
public DateClass(Activity activity) {
callerActivity = (IDateCallback)activity;
}
...
}
public void show(ArrayList<String> array) {
callerActivity.Call(array);
...
}
//And implements it inside your activity.
public class MainActivity extends Activity
implements IDateCallback {
public void call(ArrayList<String> arr) {
}
}
Well there are several things you could do. I think the easiest for you would be to send the Context into DataClass like so:
DataClass dc =new DataClass();
dc.show(this);
And in your DataClass save the context into a global var Context context. Then use it like so:
((MainActivity)context).call(array);
((MainActivity)getContext).array();
Just make a singleton like:
TeacherDashboardSingleton:
public class TeacherDashboardSingleton {
public Teacher_Dashboard aa;
private static final TeacherDashboardSingleton ourInstance = new TeacherDashboardSingleton();
public static TeacherDashboardSingleton getInstance() {
return ourInstance;
}
}
myActivity class:
onCreate(....){
....
TeacherDashboardSingleton.getInstance().aa = this;
....
}
this will create an object of same instance as in activity
now you can use it from anywhere
I have created an application in which i am sending a broadcast to my activity and in this broadcast i am sending two values, one is type and other is a badge, i am receiving these values in my inner class which is extending BroadcastReceiver but when i am going to set these values in the TextView of my main class then it is not setting these values, i am not able to understand why is this happening.
Following is my main acitivity in which inner class is present, and it is extending BroadcastReceiver :-
import java.util.List;
import android.widget.ScrollView;
import android.widget.ViewAnimator;
public class TabActivity extends Activity implements OnClickListener{
static String type;
static String badges;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
................
}
public static class TabBroadcast extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
SharedPreferences shrd = context.getSharedPreferences("Gallery", context.MODE_WORLD_READABLE);
type = shrd.getString("type", "null");
badges = shrd.getString("badge_count", "null");
badge_tips_text.setText(badge);
/*Editor edit = shrd.edit();
edit.remove("type");*/
Toast.makeText(context, "" + type + "\n" + badge_tips_text.getText().toString(), Toast.LENGTH_LONG).show();
}
}
}
I am receiving the values but unable to set them in TextView, please reply any help will be appreciable.
Thanks
You can't reference instance(non static) TextView from a static inner class. Instead, pass the stuff required through constructor:
public static class TabBroadcast extends BroadcastReceiver{
private final TextView textview;
public TabBroadcast(TextView t){
this.textview = t;
}
#Override
public void onReceive(Context context, Intent intent) {
t.setText("works");
}
}
TabBroadcast is inner class of an Activity then try as to access UI elements :
public class TabActivity extends Activity implements OnClickListener{
static String type;
static String badges;
public TextView badge_tips_text; //<<<< TextView declare here
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
................
//<<<< initilze TextView here after setContentView
}
public static class TabBroadcast extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if(TabActivity.this.badge_tips_text !=null)
TabActivity.this.badge_tips_text.setText(badge);
// your code here ...
}
}
}
and make sure you have initialized TextView before calling TextView.setText
This is happening because the broadcast receiver is running on a different thread. Try using a handler that is passed from your activity:
Where you create your broadcast class use:
new TabBroadcast(new Handler());
Pass the handler through the TabBroadcast constructor and now inside of your TabBroadcast onReceive, you can do the following:
handler.post(new Runnable() {
public void run() {
myTextview.setText("Text");
}
});
You will need to set myTextview as final