View and Activity how to share data in android.content.Context? - android

I want MyView can share data with MyActivity, so I need they can put data into Context and get data from Context, How to do that?
class MyView extends Button {
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
put data into context ...
get data from context ...
}
}
class MyActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xxx);
put data into context ...
get data from context ...
}
}
I know Activity is a instance of Context, and there is Context in the View's construtor.So I think when the Activity started, At sometime, View is trigger by event, so View put some data in Context, then at sometime, Activity is trigger by event, so it cant get data from 'Context'. I want Context to be a email box which both View and Activity send and get emails from it. I think there is some methods like put(key, val) and get(key) in Context but I not found.

You can get the context by invoking getApplicationContext(), getContext(), getBaseContext(), or this when call it in the activity class.

#malrok44 's idea is inspired me. This is my solution.
interface Interacton {
void putData(key, val)
object getData(key)
}
class MyActivity extends Activity implements Interacton {
public void oncreate() {
getData(xx)
putData(xx,yy)
}
private Map map = new HashMap
public void putData(key, val) {
map.put(key, val);
}
public object getData(key) {
return map.get(key)
}
}
class MyView extends Button {
public MyView(Context context) {
Interaction ctx = (Interaction)context;
ctx.put(xx,yy)
ctx.get(xx)
}
}
I think ThreadLocal is be ok, but I am not sure it is safe?

Related

Android: pass value to view after setContentView

New to Android and having some trouble passing data from an activity to a view. I have a simple Android onCreate method for my Activity.
public class MyActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
int num = intent.getIntExtra(MainActivity.EXTRA_NUM, 0);
setContentView(R.layout.play_game); //this is a MyView class inside of a LinearLayout
//where I want to pass the value of num to MyView
MyView myView = (MyView) findViewById(R.id.myview);
myView.setNum(num);
}
}
public class MyView extends View {
protected int num;
protected int[] array;
public MyView(Context context) {
super(context);
init();
}
public MyView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
init();
}
protected void init() {
setBackgroundResource(R.drawable.pic1);
array = new int[num];
}
public void setNum(int num) {
this.num = num;
}
}
However, I can't figure out how to pass a value to the MyView class (it extends View). I just want to send an integer value that the view class will get before starting the constructor.
Add a setter method to yours MyView class
public void setNum(int num)
{
this.num=num;
}
In MyActivity find yours view
MyView myView=(MyView) findViewById(R.id.ID_OF_YOURS_VIEW_IN_ACTIVITYS_LAYOUT);
Set yours value to yours view by passing it to setter method
myView.setNum(num);
Get your view id by findViewById() in oncreate() of MyActivity class
MyView mv=(MyView) findViewById(R.id.your-view-id);
Then set the value by a method getdata()
mv.getdata(value);
where getdata() method looks like
public void getdata(int value)
{
this.value=value;
}
after setContentView
MyView mv = (MyView) findviewById(R.id.myView);
mv.setData(int number);
You'll need to make setData public. Make sure you set the id of myview with
android:id="#+id/myView"
in xml.
You have several options :
Remove initialization of the array from init() or give it a default value for avoiding error as others suggested. It depends whether an array with a default value makes sense or not in your context. Finally inject the number with a setter.
You can also define a static method for setting the number from the activity before the view constructor get called (do it before inflating view with findViewById()). But generatly it is a bad practice and should be used in specific cases.
The real question may be : does the init() call makes sense in constructors and the array must be set at view construction? Can't it be initialized afterward?

Android. How to Get context from different activity

I'm playing with the GCM.
Everything is perfect using the example on https://code.google.com/p/gcm/source/checkout
Im getting notifications on my app with the gcm messages,
Now I want to add the message in a listView located on my MainActivity.
Im receiving my messages on a different class (GcmIntentService.java). How can I get MainActivity context to sendBroadcast.
Already tried with
private static Context mContext;
public static Context getContext() {
return mContext;
}
public static void setContext(Context context) {
mContext = context;
}
But is not working.
Any Ideas.
Thanks
I am not sure what you are doing. But keeping the below in mind
Do not keep long-lived references to a context-activity (a reference to an activity should have the same life cycle as the activity itself).
http://www.curious-creature.org/2008/12/18/avoid-memory-leaks-on-android/
You can do as below
Example:
new MyClass(ActivityName.this);
class MyClass
{
Context mContext;
public MyClass(Context context)
{
mContext=context;
}
}
pass the context variable through constructor .
create new activity like below
public class GetContext extends AppCompatActivity {
Context mainActivity;
public GetContext(Context mainActivity){
this.mainActivity = mainActivity;
}
and in your previous mainActivity send this context as below
GetContext sendContext = new GetContext(mainActivityContext);
where mainActivityContext is Context mainActivityContext = this;
or simply pass this instead of mainActivityContext
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_get_attendance_from_database);
}

How to return to main activity from onDialogClosed method in DialogPreference class

I have defined custom preference class that extends Dialogpreference class for the settings activity,
public class YesNoPreference extends DialogPreference {
private boolean mWasPositiveResult;
DashboardActivity dashboardActivity;
Context prefContext;
public YesNoPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
userSession = new UserSessions(context);
prefContext = context;
}
#Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (callChangeListener(positiveResult)) {
setValue(positiveResult);
/* Unset all user shared preferences */
userSession.unsetSessionData();
try {
dashboardActivity = new DashboardActivity();
//dashboardActivity.loginScreen();
Intent dashboard = new Intent(prefContext, DashboardActivity.class);
dashboardActivity.startActivity(dashboard);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Sets the value of this preference, and saves it to the persistent store
* if required.
*
* #param value The value of the preference.
*/
public void setValue(boolean value) {
mWasPositiveResult = value;
persistBoolean(value);
notifyDependencyChange(!value);
}
Am using the dialogprefernce to logout a user from the application. So if the user selects 'OK', the sharedprefernces are to be unset and then the user should be directed to the login page.
I tried creating a function in the Activity class and then calling it in this class. Also used Intent class, but the execution stops at
dashboardActivity.startActivity(dashboard);
and generates a Null Pointer exception.
Please help me, to find the solution.
public class SettingsActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Display the fragment as the main content.
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new SettingsFragment())
.commit();
}
}
public class SettingsFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.pref_settings);
}
}
use
prefContext.startActivity(dashboard);
instead of
dashboardActivity.startActivity(dashboard);
to access startActivity method. currently you are trying to create instance of DashboardActivity Activity for accessing startActivity method. use prefContext for starting Activity

accessing a calling activity's method from within an object it created

MyI don't understand why I get a compile error for this:
public class Main_screen extends ListActivity {
List<Object> completeList;
private My_ArrayAdapter adapter;
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
completeList = getCompleteList();
adapter = new My_ArrayAdapter(this, completeList);
setListAdapter(adapter);
}
public void doSth() {
...
}
}
and in My_ArryAdapter:
public class My_ArrayAdapter extends ArrayAdapter<Object> {
private final List<Object> list;
private final Activity context;
public My_ArrayAdapter(Activity context, List<Object> list) {
this.context = context;
this.list = list;
}
public void tryIt() {
context.doSth(); // <-------- THIS DOES NOT WORK, this method can not be called
}
}
Please explain, is there something fundamental I have not understood. I am just passing the context into the ArrayAdapter instance I create. And from within this instance I would like to acccess the caller's method.
Why shoudl this not be possible?
Many thanks!
try this:
public void tryIt() {
((Main_screen)context).doSth();
}
context is Activity and it hasn't doSth(), but Main_screen has, so you should cast to this class
Actually you are making Activity context object and passing a child of Activity (i.e Main_Screen), Its called upward cast (Implicit Casting).
So the Activity (as parent) has no method of doSth(). So you need downward Casting (Explicit casting) to make it a Main_Screen.
Two ways to do this.
make an Object of Main_Screen context instead of Activity context
or
cast it as Main_Screen in tryIt() method to avail Main_Screen methods like this way:
if(context.isInstance(Main_Screen.class))
{
((Main_Screen)context).doSth()
}
you can also use try catch to minimize the chances of ClassCastException
You can use the below code. Obviously class context don't contain an object doSth(). doSth() is declared in class Main_screen.
public class My_ArrayAdapter extends ArrayAdapter<Object> {
private final List<Object> list;
private final Activity context;
public My_ArrayAdapter(Activity context, List<Object> list) {
this.context = context;
this.list = list;
}
public void tryIt() {
Main_screen.doSth();
}
}
How I did it
StaticCommonDataClass -> maintains static data here I will keep the instance of Activity one in it.
ActivityOneClass -> Contains the method that I have to access in ActivityTwo actually.
ActivityTwoClass => Will access the ActivityOne Method.
What I hate is to pass two many parameters from one function to other function or one class to other class,
that too when it has to be done for similar values again and again.
Here i will store refrence of ActivityOneClass in static Variable.
public class CommonStaticData {
private static Activity _activity;
private static Context _context;
public static void setactivity(Activity activity) {
_activity = activity;
}
public static Activity getactivity() {
return _activity;
}
public static void setcontext(Context context) {
_context = context;
}
public static Context getcontext() {
return _context;
}
}
public class ActivityOneClass extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity1);
CommonStaticData.setactivity(ActivityOneClass.this); //will keep the instance alive for this activity
}
Public void activityOneMethod()
{
//Set of statements
}
}
public class ActivityTwoClass extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity2);
((ActivityOneClass) CommonStaticData.getactivity()).activityOneMethod();
//we need to typecast the instance stored in CommonStaticData.getactivity() to "ActivityOneClass" thats is the
//activity containing the method so as to access the method otherwise it will not come in the intellisense window and will generate Compiler Error
}
}

Android and making `this` a listener for one of its buttons

I have a custom view MyView inflated from my_view.xml (with a corresponding Java class MyView.java).
I override MyView(Context context, AttributeSet attrs) to connect subviews up to members of the class.
Now one of these subviews is a Button, and I'd like for my view to listen for a click on its button before passing this event on to a delegate. However if I declare
this.myButton.setOnClickListener(this);
in the constructor MyView(Context context, AttributeSet attrs) (where this is an instance of MyView) I get a NullPointerException.
Where is an appropriate place in MyClass.java to call this.myButton.setOnClickListener(this);?
%%
Edit. Some code:
public MyView(Context ctx, AttributeSet attrs)
{
super(context, attrs);
this.myButton = (Button) this.findViewById(R.id.my_button);
this.myButton.setOnClickListener(this); // Raises null pointer;'id' is correct.
}
Instead of trying to do the setOnClickListener(this) call in the constructor, do it after the button has been fully initialized. Try moving setOnClickListener(this) so that it's called (indirectly) from the parent activity's onResume method like this:
public class MainMenuActivity extends Activity {
#Override
public void onResume() {
super.onResume();
new MyView(this, attrs).onResume();
}
...
}
public class MyView {
public void onResume() {
myButton.setOnClickListener(this);
}
...
}
I use Roboguice all the time for this sort of thing, and highly recommend it. My button handler code looks like this:
class ButtonHandler implements OnClickListener {
#InjectView(R.id.MainMenuButton)
private Button button;
public void onResumeEvent( #Observes OnResumeEvent onResume ) {
button.setOnClickListener(this);
}
#Override
public void onClick(View v) {
doSomethingUseful();
}
}
The problem is I've missed off an inflate in the constructor:
LayoutInflater i = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
i.inflate(R.layout.my_view, this);
This is confusing for me as I'd thought the constructor MyView(Context ctx, AttributeSet attrs) would be called in inflating the view, not the other way around.

Categories

Resources