It's just something that puzzles me. Is it possible to use the current instance of the class within the constructor?
I've created a BroadcastReceiver that registers itself with the context within the constructor of the BroadcastReceiver. In addition it will unregister again. Is this good style?
Here's my example:
public class MyBroadcastReceiver extends BroadcastReceiver {
protected Context context;
protected MyOnBroadcastReceivedListener listener;
protected int receiverId;
protected String receiverTag;
public MyBroadcastReceiver(int receiverId, Context context, MyOnBroadcastReceivedListener listener, String receiverTag) {
super();
this.context = context;
this.listener = listener;
this.receiverId = receiverId;
this.receiverTag = receiverTag;
IntentFilter intentFilter = new IntentFilter(receiverTag);
context.registerReceiver(this, intentFilter); // <--- Look at the use of this here
}
public void detach() {
if (context != null) {
context.unregisterReceiver(this); // <--- Look at the use of this
}
}
#Override
public void onReceive(Context context, Intent intent) {
// ...
if (listener != null) {
listener.onBroadcastReceived(receiverId, "Bla", "Blub");
}
}
}
Yes, no trouble at all.
Inside the constructor, the object has been created but still no reference has been returned to the rest of the java code. You can use this without worries.
Anyway, in some frameworks where some attributes may be initialized automatic (Context Dependent Injection, CDI), it is not possible to fully initialize the class in the constructor (because such attributes are still not available and may be needed). These frameworks rely in that you mark a method as #PostConstruct; after all attributes are set that method will be called (just so you know what it means when you find it).
If you refer to using this in constructor code, then yes - it is perfectly valid, otherwise constructor would not be really able to construct to much within own instance. I'd however suggest following common practice and prefix your class members (most commonly used prefix is 'm') which helps avoid problems which are sometimes hard to debug. So instead of:
protected Context context;
protected MyOnBroadcastReceivedListener listener;
you would have:
protected Context mContext;
protected MyOnBroadcastReceivedListener mListener;
You can do this, but is not a good style. Passing this from inside a class constructor is dangerous as the current, still constructing object might not be fully intialized.
For example, you might one day add a new int field to the MyBroadcastReceiver, but overlook that you have the statement context.registerReceiver(this, intentFilter); and add the intialization of the new field at the end of the constructor:
public MyBroadcastReceiver(int receiverId, Context context, MyOnBroadcastReceivedListener listener, String receiverTag) {
super();
this.context = context;
this.listener = listener;
this.receiverId = receiverId;
this.receiverTag = receiverTag;
IntentFilter intentFilter = new IntentFilter(receiverTag);
context.registerReceiver(this, intentFilter); // <--- Look at the use of this here
this.newField = 1;
}
Now, you might expect that in the Context.registerReceiver method the newField to be 1 as it initialized in the MyBroadcastReceiver constructor. But you will get the value 0.
See also the following SO question for more information and more potential problems that could appear: Passing "this" in java constructor
Yes it works. I tried a simple test case. and it works. :
public class Test {
private int variable;
private Test2 test2;
public Test(int variable, Test2 test2) {
this.variable = variable;
this.test2 = test2;
test2.printTest(this);
}
public int getVariable() {
return variable;
}
public static void main(String[] args) {
Test test = new Test(111111,new Test2());
}
}
class Test2{
Test2() {
}
public void printTest(Test test){
System.out.println(test.getVariable());
}
}
And it works like a charm
Related
I want to write test case for below protected final method in java using EasyMock. Is there any way to write test case of protected final method using EasyMock ?
I tried to write TC using Reflection approach,but it didn't work.
Class < ? extends Entity > type;
private Filter filter;
private Input input;
private transient Service access;
private transient ConfigDao confdao;
protected final Limitation getBaseLimitation() {
Validate.notNull(type);
GroupClass Group = new GroupClass(GroupTypeClass.SELECTOR);
if (A.class.isAssignableFrom(type)) {
filter = new Simple(A.ATTRIBUTE_ACTIVE, Operator.EQUALS, Boolean.TRUE); //A class has static final static String ATTRIBUTE_ACTIVE = "Active";
}
if (G.class.isAssignableFrom(type)) {
filter = new Simple("position", Operator.EQUALS, Position.ACTIVE);
}
if (Boolean.TRUE.equals(confdao.getconfdao().getarea())) {
if (U.class.isAssignableFrom(type)) {
Validate.notNull(input, "switched on.");
Object Inputobj = input.getInput();
return access.getBaseLimitation(type, Inputobj, Group, filter);
}
}
return access.getBaseLimitation(type, Group, filter);
}
public Simple(String path, Operator operator, Object value) {
this(Path, operator, new Object[]{value});
}
Any help would be appreciated.
If you are mocking getBaseLimitation(), no, EasyMock can't help you because final methods can't be overridden. PowerMock could help you but I would personally just drop the final.
If you are testing it, you can from a class in the same package. But EasyMock is not needed to do so.
Then, protected final is not something useful. Why being protected if you don't want to be overloaded? You better be package scope or private.
For example,
public void show_message(String message){
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
I want this method add auto Activity.java when create new activity or java class.
I want to save different methods like this and include it in the my project quickly where it is needed.
What you should do is create a BaseActivity and make your activity extend this BaseActivity. Add all the default methods in this activity so you can use them everywhere. You can refer this Github project for reference. It uses MVP.
Here is direct link to BaseActivity.
You just need to make a Common Utilities class. Just copy and paste the class in whatever project you are using it. Just make its method access specifiers as public staic so that you can easily access it.
For e.g.
CommonUtilities.showToastMessage(String text);
What I would do is create a config class and store all these small things in it. For example have a look at this :
public class Config {
public Context context;
public String sharedPrefsName;
public String carTablesName, carsTableCarColumn, databaseName;
public int databaseNewVersion, databaseOldVersion;
public boolean showNotificationsToCustomer;
public String customerNotificationState;
public String userMobile;
public SharedPreferences preferences;
public String customerChatTableName;
public String customerChatMessageColumn;
public String customerChatSentByCustomerColumn;
public String customerChatTimeColumn;
public String loggedInUserId;
public String loggedInUserName;
public String customerChatSupportNotifyingUrl;
public Config(Context context) {
this.context = context;
customerChatSupportNotifyingUrl = "";
customerChatTableName = "customerChat";
customerChatMessageColumn = "customerMessage";
customerChatTimeColumn = "sentOn";
customerChatSentByCustomerColumn = "isSentByCustomer";
sharedPrefsName = context.getString(R.string.shared_prefs_login_validator);
preferences = context.getSharedPreferences(sharedPrefsName, Context.MODE_PRIVATE);
customerNotificationState = context.getString(R.string.customer_notification_state);
showNotificationsToCustomer = preferences.getBoolean(customerNotificationState, true);
carTablesName = context.getString(R.string.user_car_table);
carsTableCarColumn = context.getString(R.string.user_car_table_car_column);
databaseName = context.getString(R.string.user_db);
databaseNewVersion = 3;
databaseOldVersion = 1;
loggedInUserId = preferences.getString(context.getString(R.string.user_db), "");
userMobile = preferences.getString(context.getString(R.string.user_mobile), "");
loggedInUserName = preferences.getString(context.getString(R.string.user_name), "");
}
}
I've placed all the constants in a single file so you need not look at them always. If your app grows in size this would be extremely useful.
For using a progress dialog I use a class like this :
public class MyProgressDialog extends ProgressDialog {
String title, message;
public MyProgressDialog(Context context, String title, String message) {
super(context);
if (!title.equals("")) this.setTitle(title);
this.setMessage(message);
this.setCancelable(false);
this.setIndeterminate(false);
}
}
This is nothing but a single class that extends ProgressDialog.So you can aquire all the functionalities of the progress dialog class.
Similarly for toast you could do the same. If you want them to appear when the activity gets created simply keep this:
MyProgressDialog dialog=new MyProgressDialog(this,"title","message");
dialog.show();
in your activity's onCreate() method. You can do the same for toast too.
In case if it is a java class just create a constructor and keep that snippet in that constructor..
You need to read about "File Templates" https://riggaroo.co.za/custom-file-templates-android-studio/ this a large topic, but this is worth it.
I have this method :
public LeftDrawerView(Activity activity, Context context, LeftDrawerViewInterface delegate)
{
this.activity = activity;
this.context = context;
this.delegate = delegate;
}
To call above method, I call with below method :
LeftDrawerView leftDrawerView new LeftDrawerView(this, this, this);
Which might confuse later on, I wan to simplify this, is there any way to do this ?
I could call individual variables like this :
LeftDrawerView leftDrawerView new LeftDrawerView();
leftDrawerView.context = this;
leftDrawerView.activity = this;
leftDrawerView.delegate = this;
This more readable, but more code to do. want to avoid this. any suggestion would be appreciated.
You can create one more constructor which will call your existing one:
public LeftDrawerView(Activity from) {
this(from, from, from);
}
Wouldn't it be easier to just pass your CustomActivity like this:
public LeftDrawerView(CustomActivity customActivity){
this.customActivity = customActivity;
}
And than, if you need, to just cast this way:
((Activity) LeftDrawerView.this.customActivity);
((Context) LeftDrawerView.this.customActivity);
((LeftDrawerViewInterface) LeftDrawerView.this.customActivity);
What about doing this:
public LeftDrawerView () {};
Then you would create the appropriate setters:
public void setActivity(Activity activity) {...};
And finally the appropriate getters:
public Activity getActivity() {...};
public Context getContext() {...};
public LeftDrawerViewInterface getLeftDrawerViewInterface() {...};
You would use a single attribute to store the Activity instance and then, on each getter, you would do the right cast.
I was wondering if it was possible to call the methods of an external class without actually having to declare an object of that class. They way I've got it set up causes the ArrayList stored within the object empties every time the method the object is used in is called.
If I can call the method without an object, then I can fix my problem.
Thanks in advance.
calling class:
public class BookingScreen extends Activity {
GAClass sendApplication = new GAClass();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_booking_screen);
}
public void saveBookingInfo(View view) {
EditText applicantNameText = (EditText) findViewById(R.id.applicantNameTextField);
EditText itemToBurnText = (EditText) findViewById(R.id.itemToBurnTextField);
String appName = applicantNameText.getText().toString();
String appItemToBurn = itemToBurnText.getText().toString();
if (appItemToBurn.isEmpty() || appName.isEmpty()) {
Toast.makeText(BookingScreen.this, "Please fill in all fields.", Toast.LENGTH_SHORT).show();
}
else {
sendApplication.storeApplication(appName, appItemToBurn);
this.finish();
}
}
External method class:
public class GAClass {
ArrayList<Application> peopleAttending;
public void storeApplication(String name, String item){
peopleAttending = new ArrayList<>(10);
peopleAttending.add(new Application(name, item));
}
}
You can do something like below
public class GAClass {
public static ArrayList<Application> peopleAttending=null;
public static void storeApplication(String name, String item){
if(null==peopleAttending){
peopleAttending = new ArrayList();
}
peopleAttending.add(new Application(name, item));
}
}
You can invoke above method like below
GAClass.storeApplication(str_name,str_item);
when you make peopleAttending arraylist static it can be access in static method and
if(null==peopleAttending){
peopleAttending = new ArrayList();
}
Above code ensure first time initialization if peopleAttending 9s null
Use static methods. You can call a static method without creating object of enclosing class.
https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html
What exactly are you trying to achieve?
The static methods in a class would not need an instance of the class so you can make the methods you need (that do not require the state of the object - i.e. do not need a particular object to work on) static and call them like this:
ClassWithStaticMethods.staticMethod() ;
Where it is better to initialize fields? In constructor (var.1) or on declaration (var.2)?
var. 1
public class UtilWebLoading {
private int data;
private Context context;
public UtilWebLoading(Context context) {
this.context = context;
data = 100;
}
...
}
var. 2
public class UtilWebLoading {
private int data = 100;
private Context context;
public UtilWebLoading(Context context) {
this.context = context;
}
...
}
In var. 1 the context has been initiated, while in var. 2 it will be null!
Use the first one.
I personally prefer to initialize fields when I have sufficient context to do so. For example, if I have a List field I usually initialize it upon declaration (unless the class requires the user to pass an implementation of their choosing), but if I have an array that requires a size to be passed, I'm forced to wait for a constructor call.
Hence, in your case, the second snippet does not have enough context to initialize Util at declaration, because no valid Context member exists.