I have an android app and I need to pass a variable (instrument) to its main activity. It may seem like a simple question, but it confuses me. I looked around and I already noticed that it seems like a good idea to write a getInstrument method. This is what I did so far:
public class MainActivity extends Activity{
//I need to read the instrument variable here
public void addListenerOnSpinnerItemSelection(){
instrumentSp = (Spinner) findViewById(R.id.instrument);
instrumentSp.setOnItemSelectedListener(new CustomOnItemSelectedListener());
}
}
seperate class (in seperate file):
public class CustomOnItemSelectedListener implements OnItemSelectedListener {
private int instrument;
public void onItemSelected(AdapterView<?> parent, View view, int pos,long id) {
Toast.makeText(parent.getContext(),
"Please wait a minute for the instrument to be changed. ", Toast.LENGTH_SHORT).show();
//"Item : " + parent.getItemAtPosition(pos).toString() + " selected" + pos,
//Toast.LENGTH_SHORT).show();
instrument = pos;
}
public int getInstrument(){
return instrument;
}
}
But I don't think I can call the getInstrument() method from the main activity, since the object only exists within the listener. There must be a really simple way around it. I read some posts, but the problem seems to be that the object of the class does not really exist. Thanks for any insights.
You can try this :
public class MainActivity extends Activity{
//I need to read the instrument variable here
CustomOnItemSelectedListener MyListener = new CustomOnItemSelectedListener();
public void addListenerOnSpinnerItemSelection(){
instrumentSp = (Spinner) findViewById(R.id.instrument);
instrumentSp.setOnItemSelectedListener(MyListener);
}
}
If you have a reference to your listener, you should be able to call its methods, eg.
CustomOnItemSelectedListener listener = new CustomOnItemSelectedListener();
instrumentSp.setOnItemSelectedListener(listener);
....
int instrumentValue = listener.getInstrument();
Create a global instance of the
CustomOnItemSelectedListener listener;
int instrument;
public void onCreate(Bundle b){
listener = new CustomOnItemSelectedListener();
instrument = listener.getInstrument();
}
This will be on the MainActivity class
Related
PlaylistFragment starts an adapter:
playlistsAdapter = new PlaylistRecyclerAdapter(playlistsListArray, addToPlaylist, mSong, getActivity(), this);
PlaylistRecyclerAdapter binds data to the PlaylistViewHolder, something like this:
((PlaylistViewHolder) viewHolder).bind(this, dataSet.get(position), addToPlaylist, mSong);
User clicks on an item in PlaylistViewHolder:
context.startActivity(PublicPlaylistActivity.createStartIntent(context, playlist));
Now here is the question, how can PublicPlaylistActivity talk back to the initial PlaylistFragment?
I suggest you'd better use Interface from fragment to adapter. So when user clicks anything in adapter, call function realization in fragment. If you need your activity to proceed some operation - ((YourActivity) getActivity()).someMethod() should be called from fragment.
Second trick is using broadcastreceiver to send events. A bit more complicated. You have to launch broadcast in view you need to recive message and send these messages from adapter. This approach is more complexible to debug and support if system is wide spread, so you'd better use interfaces.
There are several ways of doing that. The simplest way should be starting the PublicPlaylistActivity with startActivityForResult. In that way, then the activity finishes, you can set send some data to the caller fragment (which is PlaylistFragment in your case). Here is a nice tutorial about the implementation.
Another way of doing that is by using lifecycle methods. You might have a public static variable which can keep track of some status that you might observe in your onResume function of your PlaylistFragment when you are returning back from your PublicPlaylistActivity. You might consider a sample implementation as follows.
Define a public static variable in your PlaylistFragment. Then in your onResume function check the value of that variable and take actions accordingly.
public static boolean someIndicator = false; // Initialize with a default value
#Override
protected void onResume() {
super.onResume();
if(someIndicator == true) doSomething();
else doSomethingElse();
}
Now you can set the indicator variable from anywhere in your application actually which will have the effect on your PlaylistFragment. For example, from your PublicPlaylistActivity, you might consider doing something like this.
public void someFunctionInYourPublicPlaylistActivity() {
// ...
// Some code and then the following
PlaylistFragment.someIndicator = true;
}
Another way of achieving the same thing is by using a BroadcastReceiver. Here is a tutorial on how you can implement one.
It really depends on how you are structuring your whole activity-fragments communication. Hope that helps!
I would do a common "context" class (ComContext) with an interface. When you create your fragment, you also create this class. And from the activity you can check if it exists or not.
I assume that you already have a helper(AppHelper) class with static variables.
public class AppHelper {
public static ComContext comContext = null;
}
public class MainFragment {
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ConContext comContext = new ComContext();
comContext.listener = this;
AppHelper.comContext = comContext;
}
#Override
public void onDataChanged() {
}
#Override
public void onDestroyView() {
super.onDestroyView();
AppHelper.comContext = null;
}
}
public class MainActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (AppHelper.comContext != null) {
AppHelper.comContext.listener.onDataChanged();
}
}
}
public class ComContext {
public interface HelperListener {
void onDataChanged();
}
public HelperListener listener = null;
}
im trying to send data from fragment 1, to fragment 2.
Im getting a NullPointerException, and i dont quite know why..
I have searched on google and found a lot of articles about, what im trying to do, but i just cant figure out how the general way is done, and if its even possible=(
sorry for using bad english, and im a beginner so...
Code used in Fragment 1
public interface DataMessage {
public void send(String message);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {SM = (DataMessage)activity;
}catch (ClassCastException e){
throw new ClassCastException("Implement message interface");
}
Code Used in Fragment 2
public void getData(String message){
edt.setText(message);
Log.i("Disp", "ListHistoryFragment " + message);
}
Code used in Activity
public class MyActivity extends ActionBarActivity
implements NavigationDrawerFragment.NavigationDrawerCallbacks, ListHistoryFragment.DataMessage
...
#Override
public void send(String message) {
//DisplayFragment DispFrag = (DisplayFragment) getSupportFragmentManager().findFragmentById(R.id.fragmenttest);
DisplayFragment DispFrag = new DisplayFragment();
FragmentTransaction Transfer = getSupportFragmentManager().beginTransaction();
DispFrag.getData(message);
Transfer.replace(R.id.container, DispFrag).addToBackStack(null).commit();
Log.i("Acitivyt", "ListHistoryFragment " + message);
}
Log Cat:
1-22 11:39:01.580 22399-22399/rampanere.packed.package.nl E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
at android.rampa.pack.nl.SQL.DisplayFragment.getData(DisplayFragment.java:152)
at android.rampa.pack.nl.MyActivity.send(MyActivity.java:265)
at android.rampa.pack.nl.SQL.ListHistoryFragment$1.onItemClick(ListHistoryFragment.java:73)
EDIT:
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
SM.send(message);
}
To share data between fragments and activities you should keep an instance of the data you are planning to share in your activity. SharedPreferences are intended to other purposes, for example, storing data that you will need whenever your application starts.
Inside your activity declare a protected/public String called message for example.
public class MyActivity extends .... {
public String message;
#Override
protected void onCreate(Bundle savedInstanceState) {
...
}
Inside your first fragment, whenever you want to save your String use.
((NAMEOFYOURACTIVITY) getActivity()).message = "THE STRING YOU WANT TO SHARE";
Inside your second fragment, to retrieve your message use:
((NAMEOFYOURACTiIVTY) getActivity()).message;
For example:
Log.i("The string in","my activity is: "+((NAMEOFYOURACTiIVTY) getActivity()).message);
This is the method I want to access from the Activity class (ActivityName):
public MediaPlayer getBlipComp() {
return blipComp;
}
EDIT
In the activity class
public SingleGameActivity getSingleGameActivity() {
return this;
}
This is working fine in my SurfaceView class:
SingleGameActivity myActivity = ((SingleGameActivity)getContext()).getSingleGameActivity();
// Later in the code
myActivity.getBlipStart().start();
But when I pass the reference variable to the ball (normal)-class it doesn't work:
ball = new Ball(myActivity, box.getCenterX(), box.getCenterY(), currentLvl,
Color.GREEN);
Ball-class
public Ball(SingleGameActivity activity, int xPos, int yPos, int level,
int color) {
myActivity = activity;
THIS METHOD CAN NOT BE CALLED FROM THE BALL CLASS, WHY? SOLUTION?
myActivity.getBlipPlay().start();
Pass the ActivityName instance into the constructor of NormalClass like this:
public class NormalClass {
private ActivityName activity;
public NormalClass(ActivityName activity){
this.activity = activity;
}
public void doSomething()
{
activity.getBlipComp();
}
}
this line:
ActivityName name = new ActivityName();
actually creates a new Activity show.
thats not what you want.
You have to options to do this:
1. you pass the Activity show to the "normal class" and keep it as a field:
public class NormalClass {
private Activity myActivity;
and use it as you want.
2.do the same only in the activity class.
public class MyActivity extends Activity{
public static Activity myActivity;
and int the constructor assign "MyActivity.myActivity = this;"
and than use a static method like so to use your activity:
public static MediaPlayer getBlipComp(){
return myActivity.getBlipComp();
}
and than use this method like so:
MyActivity.getBlipComp();
Have Fun!
So I'm trying to wrap my head around Android Fragments. If I put the following code in my MainActivity:
public void getMessage(Object obj) {
Log.wtf("My object: ", obj.toString());
}
and the following code in my fragment:
((NewNotificationRule)getActivity()).getMessage("Yah wohooo!");
I get the "Yah wohooo!" into my MainActivity. The thing is that this pushes that string from my fragment to my Activity, where I want it to work the other way around. The fragment just defines a couple EditTexts, so upon hitting the submit-button defined in the xml called by the MainActivity, I want the MainActivity to pull the information defined in the EditTexts within the fragment so that it can submit it into the DB. So to conclude: I want to pull something (R.id.myEditText to be precise) from within my MainActivity instead of pushing it from within the fragment.
Is there any way that I can pull the contents of an EditText from a fragment into an Activity? All tips are welcome, since I'm totally lost here..
One fast option (not sure if this is safe or recommended tho) is creating a class in your project with attributes needed to store info and instancing an object of this class in the MainActivity. Then, reference it from the fragment and fill in it the data you need to save (e.g. within an attribute EditText1Data or something) whenever the text is changed or introduced into the fragment's EditText. Then just store into the DB the data contained in the object you filled with the Fragment info. Place some default values to the atttributes in the constructor of this called class to avoid null stuff problems. This can help you easily transfer Data in both directions Activity<-->Fragments , even tho this mightmean you must be very careful since you can get null pointer exceptions.
//This is Your DataClass used to transfer Data between Activity and Fragment.
public class DataClass {
public String EditText1Value;
public String EditText2Value;
public DataManager()
{
EditText1Value="Default Text";
EditText2Value="Default Text";
}
}
//This is the MainActivityClass
public class MainActivity extends Activity{
//instance of the DataClass to be passed to fragments with the method getDataClass
public DataClass dataClass = new DataClass();
//Main Activity code goes here...
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
}
//This method returns a reference to the DataClass Object
public DataClass getDataClass()
{
//Return this class instance object of the DataClass class
return (dataClass);
}
//Now this is the method to push data to DB, called whenever an activity button is pressed.
private boolean WriteToDB ()
{
//Suppose this receives a String
WritetoDB(dataClass.EditText1Value);
}
}
//And this is the Fragment that sends data through the DataClass Object
public class ExampleFragment extends Fragment {
//Used to reference MainActivityObject and store info
DataClass dataClass;
//Used to Reference Activity's EditTexts
private EditText editText1;
//TextWatcher used to detect the EditText Field Changes
private TextWatcher EditText1_Txtwtr;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View v = inflater.inflate(R.layout.whatever_layout, container, false);
editText1= (EditText)v.findViewById(R.id.idEditText1);
setHasOptionsMenu(true);
return v;
}
#Override
public void onResume ()
{
super.onResume();
//code...
//Get MainActivity's DataClass object reference.
dataClass= ((MainActivity)getActivity()).getDataClass();
//store info whenever you need to, not necessarily on each keystroke, and store it in the object, not in the DB
dataClass.EditText1Value = editText1.getText().toString();
// Also, to capture whenever a edittext changes, you can use a textwatcher.
EditText1_Txtwtr= new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3)
{}
#Override
public void afterTextChanged(Editable editable)
{}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3)
{
dataClass.EditText1Value = editText1.getText().toString();
}
}
//Asign TextWatcher to your Edit Text.
editText1.addTextChangedListener(EditText1_Txtwtr);
}
}
I have been developing a simple touch handler for Android with the possibilites of firing callbacks like onUpdate (when the screen is touched) without having to setup threads. My problem is that my knowledge of Java is fairly limited and i can't do it because i know very little of how to use interfaces. I'm pretty sure that my problem may be a simple typo or something, but i get a NullPointerException when i execute the method from the touch handler (which processed the touch information) so that i can do what i need in the main activity class.
This is the main class code (cut from the irrelevant stuff):
//package and imports
public class Test extends Activity implements TouchHelper {
StringBuilder builder = new StringBuilder();
TextView textView;
TouchReader touchReader;
List<TouchTable> touchTablesArray;
TouchTable touchTable;
public static final String Tag = "TouchTest";
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
textView = new TextView(this);
Log.d(Tag, "TextView initialized " + textView);
textView.setText("Touch and drag (multiple fingers supported)!");
touchReader = new TouchReader(textView);
Log.d(Tag, "touchReader initialized");
touchTablesArray = touchReader.getTouchTables();
setContentView(textView);
}
#Override
public void onTouchUpdate(int pointerId)
{
Log.d(Tag, "onTouchUpdate called");
touchTable = touchTablesArray.get(pointerId);
Log.d(Tag, "touchTable get successful");
//writing on stringbuilder
}
}
This is the code of the handler itself:
//package and imports
public class TouchReader implements OnTouchListener
{
public final static String Tag = "TouchReader";
List<TouchTable> touchTables;
TouchHelper helper;
TouchTable touchTable = new TouchTable();
public TouchReader(View view)
{
view.setOnTouchListener(this);
touchTables = new ArrayList<TouchTable>(10);
Log.d(Tag, "TouchReader initialized");
}
public boolean onTouch(View v, MotionEvent event)
{
synchronized(this)
{
//all the common code handling the actual handling, with switches and such
touchTables.add(pointerId, touchTable); //obviously the pointerId is defined earlier
Log.d(Tag, "Values updated");
helper.onTouchUpdate(pointerId); //the exception is here
Log.d(Tag, "Update called");
}
return true;
}
public List<TouchTable> getTouchTables()
{
synchronized(this)
{
return touchTables;
}
}
}
As you can see the error is most likely due to my inability to correctly use an interface, and yet all the official docs confused me even more.
Finally, the tiny code of the interface:
//package
public interface TouchHelper
{
public void onTouchUpdate(int pointerId);
}
I hope this question isn't too noobish to post it here :)
EDIT: Thanks to all for the help, in the end i followed Bughi's solution.
Your TouchHelper helper; is null, it needs a instance of the interface to be able to call methods on it -in your case the main activity class that implements your interface-
Make a set method for the listener
public void setOnTouchListener(TouchHelper helper)
{
this.helper = helper;
}
Then call it from on create:
public class Test extends Activity implements TouchHelper {
...
#Override
public void onCreate(Bundle savedInstanceState)
{
...
touchReader = new TouchReader(textView);
touchReader.setOnTouchListener(this);
...
}
}
Also add a null check to your on touch method:
public boolean onTouch(View v, MotionEvent event)
{
synchronized(this)
{
//all the common code handling the actual handling, with switches and such
touchTables.add(pointerId, touchTable); //obviously the pointerId is defined earlier
Log.d(Tag, "Values updated");
if (helper != null)
helper.onTouchUpdate(pointerId); //the exception is here
Log.d(Tag, "Update called");
}
return true;
}
If the NullPointerException is here:
helper.onTouchUpdate(pointerId);
Then simply helper is null, where do you initialize it?
I see that you define it:
TouchHelper helper;
But do you ever have?
helper = ...
I know this is old, but I was stuck on this myself. Sam's post above helped me think of it.
I finally added an onAttach method that that checks that the interface is initialized as well as implemented to the main activity that it interfaces with. I added a Log.i inside the main activity to test.
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mainActivityCallback = (OnSomethingSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnSomethingSelectedListener");
}
}
In TouchReader you define a TouchHelper but nowhere in the code an object is created or an existing object is assigned to that attribute. So it is still null when you try to use it.
helper is null in your in TouchReader
To fix this make the TouchReader take a TouchHelper:
public TouchReader(View view, TouchHelper helper) {
...
this.helper = helper;
...
}
Then in your activity:
touchReader = new TouchReader(textView, this);
Try initializing it in your constructor; all reference that aren't initialized are set to null.
// I see no reason why this should be a member variable; make it local
StringBuilder builder = new StringBuilder();
TextView textView;
TouchReader touchReader;
List<TouchTable> touchTablesArray;
TouchTable touchTable;
public TouchReader(View view)
{
// textView is null
// touchReader is null
view.setOnTouchListener(this);
// why "10"? why a List of touchTables and a touchTable member variable? why both?
touchTables = new ArrayList<TouchTable>(10);
Log.d(Tag, "TouchReader initialized");
// touchTable is null;
}