I simply have not found a solution to share a real-time data between the activitys. My first activity receives real-time object (type double, a random numbers). And i want to pas this numbers to second activity. It all works, only the second Activity shows only one time the data. I have to refresh the activity by going back to first activity and only then the second activity show the latest data. I implemented a Singelton pattern:
public class FirstActivity extends Activity{
public double xAxis;
public double yAxis;
public static FirstView instance;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.device_view);
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
int data1 = msg.arg1;
xAxis = (double) data1;
dataX.setText(String.valueOf(xAxis));
int data2 = msg.arg2;
yAxis = (double) data2;
dataY.setText(String.valueOf(yAxis));
}
};
secondview.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent nextScreen = new Intent(getApplicationContext(),
SecondActivity.class);
startActivity(nextScreen);
}
});
}
public static void initInstance(){
if(instance == null)
{
instance = new FirstActivity();
}
}
public static FirstActivity getInstance(){
return instance;
}
}
SecondView class
public class SecondActivity extends Activity{
private double valueX;
private double valueY;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.linegraph);
valueX = FirstActivity.getInstance().xAxis;
valueY = FirstActivity.getInstance().yAxis;
}
}
Application class
package com.bluetoothcomm;
import android.app.Application;
public class MyApplication extends Application {
#Override
public void onCreate(){
super.onCreate();
initSingeltons();
}
public void initSingeltons(){
FirstActivity.initInstance();
}
}
You may implement a background service capable of providing the real time data to Activity1 and also to Activity2. I am guessing that your problem ocurrs if you are passing data from Activity1 to Activity2 through an Intent with putExtras, on this way it will only do this at the moment you start Activity2.
I have found my problem and the solution is to use Application. Only this dose not solves my problem. The problem is that the static variable instance public static FirstView instance is bound to the class loader, the first class that initilize that. So when the static variable inside any class has been initilized by an Activity and when the second Activity is started the first Activity is destroyed, so this means the static variable is also uninitilized. Thats why the SecondActivity dose not gets the up to date data or real time data, it catches only static constant data.
I changed my code a littele bit with the combination of Singelton and Application, couse this way the static variable should never be uninitilized when SecondActivity is activated. But i still get the same results, the static variable instance is uninitilized when i swtich to Second Activity. I am doing somethink wrong, does any one sees it. I added my code.
#Max Rasguido, #Orabig
You should use the intent process. docs
How is your data supposed to change when activity2 is shown, if you say that it's received by activity1 ?
However, I would use a preference, or an attribute of your application class (which is a singleton itself), but you give too little informations to fully understand your needs...
Related
I'm new to android and I am making an app as part of an assignment, and can't get this function to return a value - the app closes and I get an error message: "Unfortunately, APP has stopped".
I have two classes, one is the MainActivity and one is a class that I am wanting to use to do arithmetic, and they are:
import com.calc.Calculation;
public class MainActivity extends Activity {
private Calculation util;
calculate = (Button) findViewById(R.id.btnCalc);
private TextView tvMultiply;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvMultiply = (TextView) findViewById(R.id.tvMult);
}
btnCalc.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
tvMiltiply.setText(String.valueOf(util.CalculateMult(4,6)));
}
});
}
and
package com.calc;
public class Calculation{
public int CalculateMult(int numOne, int numTwo)
{
return numOne * numTwo;
}
}
I've tried a few alternatives but to no avail. It's going to be something simple that I am not doing quite right.
Any help appreciated.
Thanks
You need to create instance to the class before acccessing the member.
private Calculation util = new Calculation()
Else make the method in the class as static and access without creating instance.
This would be done by defining the class as:
package com.calc;
public class Calculation{
public static int CalculateMult(int numOne, int numTwo)
{
return numOne * numTwo;
}
}
and calling the method as:
Calculation.CalculateMult(4,6)
You should move the line
calculate = (Button) findViewById(R.id.btnCalc);
to the onCreate() function after you have set the content view. You should also move the assignment of the onClickListener to your button to the onCreate() method.
Finally, you should initialize your Calculation object by using the new operator in onCreate(), i.e:
util = new Calculation();
First, I am an android rookie, so my solution ways can be found awkward, and i am open to suggestions.
I am trying to create a game manager object that handles all transitions between activities. And my purpose is that while in an activity, menuOut method will call the changeActivity method of GameManager object with nextActivity argument and changeActivity will start that Activity. I am getting errors consistently, and did not find a solution.
Here is my source codes:
GameManager:
public class GameManager{
public SplashScreen splash = new SplashScreen();
public MainScreen main = new MainScreen();
public LoadingScreen load = new LoadingScreen();
Context tempContext;
public GameManager(Context base) {
super();
tempContext = base;
}
public void start(){
createScreens();
Intent intent = new Intent(tempContext, splash.getClass());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
tempContext.startActivity(intent);
}
public void createScreens() {
//here is the method that i am trying to find a solution
((SplashScreen)splash.getContext()).setGameClass(this);
((MainScreen)main.getContext()).setGameClass(this);
((LoadingScreen)load.getContext()).setGameClass(this);
}
public void changeMenu(MenuType nextMenu, MenuType previousMenu){
Intent intent2;
switch(nextMenu){
case MAIN_SC:
tempContext = main.getContext();
intent2.setClass(tempContext, main.getClass());
intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
tempContext.startActivity(intent2);
case GAME_LOADING_SC:
tempContext = load.getContext();
intent2.setClass(tempContext, load.getClass());
intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
tempContext.startActivity(intent2);
default:
break;
}
}
}
And here is SplashScreen activity:
public class SplashScreen extends Activity {
public Context context = this;
public GameManager gameman;
private static final int SPLASH_DURATION = 4000;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
splash();
menuOut();
}
public Context getContext() {
return this;
}
public void splash() {
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.HORIZONTAL);
ll.setBackgroundResource(R.drawable.game_loop_splash);
setContentView(ll);
Handler handler = new Handler();
// run a thread after 2 seconds to start the home screen
handler.postDelayed(new Runnable() {
#Override
public void run() {
finish();
}
}, SPLASH_DURATION);
}
public void setGameClass(GameManager game){
gameman = game;
}
private void menuOut(){
gameman.changeMenu(MenuType.GAME_LOADING_SC, MenuType.GAME_SPLASH_SC);
this.onDestroy();
}
}
I can not return to the GameManager and call the changeMenu method.
I am very exhausted to get null pointer exceptions.
Any idea?
From what I read, you are trying to implement a singleton pattern. There are two ways I'd recommend to do that on android:
Extend the Application class, register your class in the manifest and use getApplication() in your activities to get access to it:
// In MyApplicationSubclass.java:
public final class MyApplicationSubclass extends Application {
/* ... */
public void myMethod() {
// insert some code here
}
/* ... */
}
// From your Activity:
((MyApplicationSubclass) this.getApplication()).myMethod();
Use a "normal" java singleton pattern, e.g. use a private constructor and keep one static instance within your GameManager class (this is the way the Android docs recommend, but I personally prefer the first way when having something that is logically bound to the Application).
Also, if you're only using your central class to do static stuff, you can just mark all its method as static and access them directly. Transfer Context objects as parameters to these methods, and you should be able to start activities without any static variables (which are sometimes hard to implement properly in Android, as your VM might get restarted from time to time).
I stuck at this issue many times and I passed the problem in different ways and I'm not sure that I made it in the right way.
I simplified the problem in a the following example. I know that I can pass only the data to the class but I do want to pass the editText cause I have this problem with more difficult UI controls.
mainactivity.java
public class mainactivity extends Activity {
public EditText clickEditText;
int count =0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
newTxt();
}
public void newTxt() {
txt = new MyText(context);
txt.updateTextEdit("Main Activity");
}
}
myText.java
public class MyText
{
private Context _context;
// constructor
public MyText(Context context)
{
_context = context;
}
public void updateTextEdit(String str)
{
private EditText strEditText;
strEditText= (EditText)findViewById(_context.R.id.editTextClick); // ????
strEditText.setText(str + " and myTxt");
}
}
if you could explain me how to fix the updateTextEdit function. i passed the context of the main activity. How can I change the editText? Thank you very much!!!
If you really want to do this this way, you need to save a reference to Activity, not Context. Like this:
public class MyText
{
private Activity _activity;
// constructor
public MyText(Activity activity)
{
_activity= activity;
}
public void updateTextEdit(String str)
{
private EditText strEditText;
strEditText= (EditText)activity.findViewById(R.id.editTextClick);
strEditText.setText(str + " and myTxt");
}
}
and in newTxt() you will need to change:
txt = new MyText(context);
to:
txt = new MyText(this);
But wouldn't it be easier to just put this method inside your activity? Why do you want it in another class? If it really needs to be in another class, you could make that class an inner class of your activity and you would still have access to the activity's methods and member variables.
There's a similar question here
How to access Activity UI from my class?
You didn't say how you obtained the context, you should use this and get the mainactivity in the other class. not context.
then you can call runOnUIThread to perform UI updates.
I am currently working on an android project and I have an activity, lets call it MyActivity and this activity calls a standard Java class called MyClass.
I need MyClass to finish the MyActivity activity but I can't find out how to do this. I thought I might be able to pass the context to the standard java class and call context.finish() but this doesn't appear to be available.
How can I do this, thanks for any help you can offer.
You can pass the Context, but you will need to cast it to an Activity (or simply pass the Activity itself), although this in general seems like a bad practice.
The most secure solution uses listener and a Handler. It is complex, but ensures a non direct call to finish activity.
Your listener:
interface OnWantToCloseListener{
public void onWantToClose();
}
Class that should close activity.
class MyClass {
private OnWantToCloseListener listener;
public void setWantToCloseListener(OnWantToCloseListener listener){
this.listener = listener;
}
private void fireOnWantToClose(){
if(this.listener != null)
listener.onWantToClose();
}
}
When you want to close your activity you must call fireOnWantToClose() method.
public MyActivity extends Activity{
public void onCreate(){
final int CLOSE = 1; //number to identify what happens
MyClass my_class = new MyClass();
final Handler handler = new Handler(){
public void handleMessage(Message msg){
if(msg.what == CLOSE)
MyActivity.this.finish();
}
});
my_class.setOnWantToCloseListener(new OnWantToCloseListener(){
public void onWantToClose(){
handler.sendEmptyMessage(CLOSE);
}
});
}
}
This is secure because Activity is not finished directly by MyClass object, it is finished through a listener that orders a handler to finish activity. Even if you run MyClass object on a second thread this code will works nice.
EDIT: CLOSE var added I forget to declare and initialize this.
Pass the MyActivity to MyClass as an Activity. From there you can call myActivity.finish();
For example:
private Activity myActivity;
public MyClass(Activity myActivity){
this.myActivity = myActivity;
}
public void stopMyActivity(){
myActivity.finish();
}
And in MyActivity:
MyClass myClass = new MyClass(this);
This is risky, because you're holding a reference to an Activity, which can cause memory leaks.
If your java class is a nested inner class, you can use:
public class MyActivity extends Activity {
public static class JavaClass {
public void finishActivity() {
MyActivity.finish();
}
}
}
Otherwise you'll have to pass the java class a Context (i.e. pass it a reference to this, since Activity extends Context) and store it as a private instance variable.
my dear friends. Could you help me to figure out where do I have memory leak in my application.
There are two activities.
In first activity I'v got a rather big static ArrayList consists of bitmaps and another needed information. I made it static, because I need to take it from another activity, and It's loading takes to much time.
In another activity, I also have one static field, using as a key for getting data which present in an Intent from previous activity.
If I try to start one activity from another and go back several times, I get shutting down VM.
To be more clear, here is a snippet of my code:
public class MoviesGallery extends Activity
{
...
private static ArrayList<Movie> films = new ArrayList<Movie>();
...
public void contextButtonsClickHandler(View v)
{
switch(v.getId())
{
case R.id.play_button:
Log.d("Context Button", "Play button has clicked");
mContextButtonHasPressed = true;
Intent filmData = new Intent(MoviesGallery.this, MovieInfo.class);
filmData.putExtra(MovieInfo.mPOS,mPOSITION_OF_CLICKED_ITEM);
startActivityForResult(filmData, 1);
break;
...
}
And this is another activity:
public class FilmInfo extends Activity
{
public static String mPOS = "pos";
private int mNumOfFilm = -1;
private LinearLayout mWall;
...
protected void onCreate(Bundle savedInstanceState)
{
Bundle extra = getIntent().getExtras();
mNumOfFilm=extra.getInt(mPOS);
...
Drawable d = new BitmapDrawable(MoviesGallery.getMoviesArray().get(mNumOfFilm).getWall()));
mWall = (LinearLayout) findViewById(R.id.Wall);
mWall.setBackgroundDrawable(d);
...
setResult(0);
}
I would suggest that potentially memory-leak point is in FilmInfo class member:
private LinearLayout mWall;
Layout has reference to Activity, which each time changes.
So to avoid keeping reference to dead Activity just use in FilmInfo class
#Override
public boolean onContextItemSelected(MenuItem item)
{
//blah-blah
mWall=null;
}
Anyway recipe is simple - try to avoid keeping objects which might contain references to Activity/Context objects.