I was kind of stuck trying to pass the resources to a subclass used on my Activity. I solved it in two ways, but not sure if one or both will lead to possible memory leaks. So here is what I have so far:
-myactivity (the activity class)
-global (global class to the package, I'm using to to save global accesible variables)
-subclass (the subclass where I want to use a drawable resource)
a)
public class global{
public static Resources appRes;
....
}
public class myactivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
global.resApp = this.getResources();
...
}
private void somewhere(){
subclass tmp = new subclass();
tmp.subclasmethod();
}
}
public class subclass{
public subclass(){...}
public void subclassmethod(){
Bitmap bmp = BitmapFactory.decodeResource(Global.appRes, R.drawable.myres);
...
}
}
b)
public class myactivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
}
private void somewhere(){
subclass tmp = new subclass(this.getContext());
tmp.subclasmethod();
}
}
public class subclass{
Context context;
public subclass(Context context){
this.context = context
...
}
public void subclassmethod(){
Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), R.drawable.myres);
...
}
}
Thanks in advance for you feedback.
If you want a global class to store application-wide values, you should at least not use your option a. Instead, take a look at the Application class, which is meant to help you with exactly this:
Base class for those who need to
maintain global application state.
Otherwise, the alternative you suggest in option b is an OK way to do it. At least if all you need is to pass along a reference to your application context so that you can access the resources.
Related
Here is my main activity:
public class MainMenu extends AppCompatActivity implements BluetoothSerialListener, BluetoothDeviceListDialog.OnDeviceSelectedListener {
public static BluetoothSerial bluetoothSerial;
public onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
[...]
bluetoothSerial = new BluetoothSerial(this, this);
bluetoothSerial.setup();
}
And this is my other activity:
public class LaunchGame extends MainMenu {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
[...]
BluetoothSerial bluetoothTest = MainMenu.bluetoothSerial;
}
The problem is when I want to make some stuff on bluetoothTest (second activity), the object is null and I need to keep the bluetooth configuration between the two activities...
How can I make this object persistent between them ?
Regards
Make BluetoothSerial a singleton by using the Singleton Pattern. Make sure that BluetoothSerial is not holding onto context, views or other system resources. You can also make BluetoothSerial thread safe if needed.
I have two fragments (each a tab in a sliding tab activity) in my application. The two fragments have some methods which now are identical, I thought that I could abstract out those methods to follow the DRY (don't repeat yourself) principle. Is there any recommended way of doing this?
Is a util class with static methods a good way? Or should I create an abstract class "MyAbstractFragment" which has those methods and let the fragments extend this class?
For example.
public class MyCustomFragment extends Fragment {
protected LinearLayout linearLayout;
protected MyAdapter adapter;
//more common fields
void addButtonToFragmentView(final String btnText) {
final Button btn = new Button(getContext());
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
linearLayout.removeView(btn);
}
});
btn.setText(btnText);
linearLayout.addView(btn);
}
void upDateAdapterList(List<String> list){
//....
adapter.updateList(list);
}
}
Than my fragments could extend this class and set the properties and use the methods. But I also see that I as well could make a static util class just for the methods, like addButtonToFragmentView(final String btnText, Context context, final LinearLayout linearLayout) and upDateAdapterList(List<String> list, MyAdapter adapter)
Or is there a preferred way of doing this?
Yes, you can use abstract class like below:
public abstract class BaseFragment extends Fragment {
#Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
public Context getContext() {
return this.getActivity().getApplicationContext();
}
protected abstract void addButtonToFragmentView(final String btnText);
protected abstract void upDateAdapterList(List<String> list){
}
then extends your new fragment with this base class.
code taken from:
https://github.com/spirosoik/AndroidArchitecturePadawans/blob/master/presentation/src/main/java/com/architecture/padawans/views/common/BaseFragment.java
We should try to follow composition over inheritance. May be you can have a dedicated UIFactory class which deals with dynamic creation of views, then you move your addButtonToFragmentView method to the UI factory and make if more generic.
void addButtonToView(final String btnText, final Context, final View parentView);
As far as upDateAdapterList is concerned you can create a BaseListFragment and move it there, so whoever is interested in using a fragment with List can extend this Fragment. Hence this follows Single Responsibility Principle.
I have an Activity in whose onCreate() method i call a Utility function.
This utility functions requires a callback class instance as a parameter, in which it returns the info that i need. this is:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Utility.functionA(new functionACallBack() {
/**
*
*/
private static final long serialVersionUID = -7896922737679366614L;
#Override
public void onResponse(String error) {
((MyActivity) AppClass.getAppContext()).finish();
}
});
}
Once I have obtained that info, I want to close the activity. so i called finish() from inside the anonymous class that i created for the callback.
But the activity is not getting finished. I thought maybe i need to call finish() from UI thread so i did runOnUiThread(), in inside it also i tried calling finish(). But it just doesn't work.
Could someone please help me with this issue?
UPDATE:
I am storing APP context and then trying to use that but to no avail.
public class AppClass extends Application {
private static Context mContext;
#Override
public void onCreate() {
super.onCreate();
AppClass.mContext = getApplicationContext();
}
public static Context getAppContext(){
return AppClass.mContext;
}
}
Simply call something like this:
#Override
public void onResponse(String error) {
((Activity) context).finish();
}
As this is a static function, you'll have to be able to access your Context in a static way. You can save that as a Class variable, but you'll have to be aware about its handling as it might lead to memory leaks.
To avoid them, you can declare a class that extends Application and save here your context, so this way you won't ever have a memory leak.
Try using this code:
((Activity) ActivityClass.this).finish();
Remember, use the Activity class, not the Application one.
I have a non-activity class that needs to launch a new activity. Right now I just pass the current context as a parameter, but I would like to access the context statically if possible. I've already tried creating a new application (MyApplication extends Application), both as a new application and the main application, and neither worked. Any suggestions?
Current Code:
public class SharedFunctions {
public static void doSomething(Context context){
Intent i = new Intent(context, NextActivity.class);
context.startActivity(i);
}
}
The cleaner way to do it is to pass in a Context to each method. It's more typing, but it helps to make sure you're not leaking the reference.
Of course, if you really need static reference to it, you can just keep a static member in your SharedFunctions class and set it for each Activity.
onResume() and onPause() may be good places to set/clear it, but depending on your needs, you might want to change it. Just try not to keep references to old Activities.
public class SharedFunctions{
private static Context context;
public static void setContext(Context ctx){
context = ctx;
}
public static void doSomething(){
context.someContextFunction();
}
}
In each Activity:
protected void onResume(){
SharedFunctions.setContext(this);
}
protected void onPause(){
SharedFunctions.setContext(null);
}
create this class:
public class MyApplication
extends Application
{
private static Context context;
#Override
public void onCreate()
{
super.onCreate();
context = getApplicationContext();
}
public static Context getContext()
{
return context;
}
}
after that you must add this class to field name in application (Manifest)
<application
android:name="yourPackageName.MyApplication"
........
</application >
As a result you can call MyApplication.getContext() anywhere in your application and get the context.
hope, I help you.
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.