How to use overridden Methods in an Activity as own Methods - java

I created an App, where I get answers from my Server to my HelperClass. The HelperClass has several #override Methods. This I override this Methods in every activity different.
So now my Problem is, I get lots of Problems, casue of multi threading. For example with a simple Toast. I have to use runOnUiThread() every time. Or "Only the original thread that created a view hierarchy can touch its views." when a overridden Helperclass method should use a (for example) MainActivity-Method to set a new layout.
Is there any solution, how I can solve those problems?
Code example:
public abstract class HelperClass extends AppCompatActivity{
#Override
public void methodOne() { }
#Override
public void methodTwo() { }
}
Here are my Methods defined. An another Class gets the answer from the Server and call them. (everything works).
I override them in every Activity (here for example MainActivity)
public class MainActivity extends HelperClass {
#Override
protected void onCreate(Bundle savedInstanceState){
setContentView(R.layout.first_layout);
}
#Override
public void methodOne() {
Toast.makeText(this,"text",Toast.LENGTH_SHORT).show();
}
#Override
public void methodTwo() {
setContentView(R.layout.second_layout);
}
}
So I will get Error, when I use them without runUIThread(). I need a solution for everywhere, cause I think this is not clean. There should be a better way then using runUIthread() in every single method, when I want to use a View or something else (till now I only had this two Problems, there are still 20-30 Funktions to declare).

Related

What is the advantage of creating an instance of an Interface Class instead of just adding that Interface to the main class for Callbacks?

I am working on an Android app and I came across the following code for a set of Callbacks from C++.
I am wondering why, using an instance of the interface class JNIListener instead of implementing the interface and adding the Callbacks directly, makes sense.
public interface JNIListener {
void onProcessingStarted();
void onResultAvailable();
}
public class MainFragment extends Fragment {
......
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
.....
mListener = new JNIListener() {
#Override
public void onProcessingStarted() {
NavDirections action = MainFragmentDirections.actionMainFragmentToResultFragment();
NavHostFragment.findNavController(ThisFragment).navigate(action);
}
#Override
public void onResultAvailable(){
....
}
}
subscribeListener(mListener);
}
}
instead of :
public class MainFragment extends Fragment implements JNIListener{
......
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
.....
subscribeListener(this);
}
#Override
public void onProcessingStarted() {
NavDirections action = MainFragmentDirections.actionMainFragmentToResultFragment();
NavHostFragment.findNavController(thisFragment).navigate(action);
}
#Override
public void onResultAvailable(){
....
}
}
I don't get the advantages of the first approach.
The second makes more sense to me: The callbacks have complete access to the members of the MainFragment.
The first approach should have its pro, otherwise why would someone have done it that way.
The person who wrote that code is for sure more experienced than I am. If I am doing something weird by preferring the second approach, it would be nice to understand why it is weird, learn something and avoid the issue next time.
The only advantage for the first approach is If you need two or more interfaces for separate things in your class. In every other case, I would use the second approach since it makes the code looks cleaner.

How to inject an object passed to the BaseActivity, instantiating it with reflection (or any other way if possible)

I have a BaseActivity, in which I am trying to retrieve the instance of a subclass in order to inject it with dagger.
I've been trying to figure out a way to not check manually the object passed on is an instance of every single Activity, but if there is a more optimal way of doing it.
F.i., if the component is as such:
AppComponent
#Singleton
#Component(modules = {AppModule.class})
public class AppComponent {
public void inject(FooActivity fooActivity);
public void inject(BarActivity barActivity);
public void inject(…);
}
Each activity extends BaseActivity and we have something like:
FooActivity
public class FooActivity extends BaseActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.inject(this);
}
}
Last, the issue comes when handling the BaseActivity.
BaseActivity
current implementation
...
public void inject(FooActivity fooActivity) {
DaggerAppComponent.create().inject(fooActivity)
}
public void inject(BarActivity barActivity) {
DaggerAppComponent.create().inject(barActivity)
}
...
However, I am looking for a more optimal way that reduces boilerplate, so I have been thinking something like the following:
BaseActivity
...
public void inject(Object activity) {
// retrieve the instance of the activity
// if possible and handle it so then we can:
DaggerAppComponent.create().inject(activity)
}
...
But since I am required to find its instance, instead of having a series of if statements with instanceof, which I will need to update for every new activity, is there a way to handle it in a more automated way?

Can't understand use of this keyword in View.setOnClickListner(this)?

I know that keyword this refers to current instance of class. But When we implement View.OnClickListener in our class then on calling method textview.setOnClickListener(this), How does argument this(instance object of class) of setOnClickListener(this) call automatically onClick() method. Is there any code in view class which take object and call onClick method on this code or something else is going on?
I want to know what is going behind the scenes, how does android reaches from this keyword to onClick() method? That is what I want to ask?
OnClickListener is an interface in class View.
If your activity implements this interface by setting:
public class MainActivity extends AppCompatActivity implements View.OnClickListener
then you can set a listener for a view like button:
myButton.setOnClickListener(this);
and override the onClick method implementing it like this:
#Override
public void onClick(View v) {
// your code here
}
so a simple explanation is: this means that your view will use your activity's overridden onClick method.
To implement the View.setOnclickListener in your code you need to first implement the public static interface View.OnClickListener.
like this
public class MyActivity extends Activity implements View.OnClickListener {
}
The above interface contains public void abstract method "onClick(View v)" which you override to put your logics
This method is called when a view has been clicked.
for sake of simplicity i have created the code
// Create an anonymous implementation of OnClickListener
private OnClickListener mCorkyListener = new OnClickListener() {
public void onClick(View v) {
// do something when the button is clicked
}
};
protected void onCreate(Bundle savedValues) {
...
// Capture our button from layout
Button button = (Button)findViewById(R.id.corky);
// Register the onClick listener with the implementation above
button.setOnClickListener(mCorkyListener);
...
}
here OnclickListener is an interface which have object mCorkyListener
similarly you can use this keyword instead mCorkyListener
‘this’ represents the instance of the current class. You can access the properties and functions of the current class with ‘this’ keyword.
Let's have an interface ElectricityBill
public interface ElectricityBill{
public void pay(int amount);
}
now there are two ways you can pay an electricity bill either by going to nearby electricity board office
ElectricityBill bill = new ElectricityBill(){
#Override
public void pay(int amount){
}
}
payBill(bill);
or by paying the bill online
public class User implements ElectricityBill{
.....
#Override
public void pay(int amount){
}
}
.....
payBill(this);
}
in both the cases, the user has to pay XXX amount, similar is the case if you want to listen to input events you either have to pass the original View.OnClickListener object or implement it and pass this to make it work.
Edit:
when you pass this you tell the current class to handle the click events itself and has to override the onClick() to do so. And when you pass object you let the original class to handle the onClick by creating an anonymouse class and implementing onClick(). but when you pass this your current class get's the authority to listen to input events. It becomes on the type of OnClicklistener and gets the authority to listen onClick()

Why can I not call the interface method?

Disclaimer: I'm coming from Swift so my idea on how delegation works is biased.
I have an interface defined:
public interface IChatButtonResponse {
void chat(ListingEntry listingEntry, String initialUserText);
}
My class has a local reference to it that is saved when instantiated:
public class ListingAdapter extends BaseAdapter {
private IChatButtonResponse delegate;
public ListingAdapter(Context context, ArrayList<ListingEntry> listingEntries, IChatButtonResponse delegate) {
this.delegate = delegate;
When I try to call the delegate in response to a button tap, I get a compilation error:
chatButton.setOnClickListener(new View.OnClickListener() {
delegate.chat(listingEntry, null); // Cannot resolve symbol 'chat'
});
Why can it not be resolved? I tried to make the method declaration in the interface public but that didn't change anything. (I would have been surprised if it did)
EDIT:
My usage of the interface in the same package:
public class MainActivity extends AppCompatActivity implements IChatButtonResponse {
.
.
.
#Override
void chat(ListingEntry listingEntry, String initialUserText) {
}
I am getting a compilation error here: 'chat(ListingEntry, String)' in ...sample.app.MainActivity' clashes with 'chat(ListingEntry, String) in ...sample.app.IChatButtonResponse'; attempting to assign weaker access privileges ('package-private'); was 'public'
Tried making the implementation method public with no change.
For the original error in question, the clue was found on another error I hadn't noticed earlier on the chatButton.setOnClickListener.
The OnClickListener method onClick must be overridden like this:
chatButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String referenceID = listingEntry.referenceID;
delegate.chat(listingEntry,null);
}
});
This fixes the resolution error at the call site.

Inner class which extends Asynctask and outer class extends Activity and then Extend outer class from another Activity. Is this a bad practice?

Is this bad practice?
import android.app.Activity;
import android.os.AsyncTask;
public abstract class Asynch extends Activity {
public abstract void doInBackgroundAbstract();
public abstract void onPostExecuteAbstract();
protected class AsynchtaskSubClass extends AsyncTask {
#Override
protected Object doInBackground(Object... arg0) {
doInBackgroundAbstract();
return null;
}
protected void onPostExecute(Object result){
onPostExecuteAbstract();
}
}
}
public class SomeActivity extends Asynch {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_classes);
new AsynchtaskSubClass().execute();
}
private Document doc;
#Override
public void doInBackgroundAbstract() {
// NETWORK OPERATION GOES HERE!
try {
doc = Jsoup.connect("mySite").get();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onPostExecuteAbstract() {
// Update UI Thread Here
TextView myTextView = new TextView(SomeActivity.this);
myTextView.setText(doc.select("a[href]").attr("abs:href").toString());
setContentView(myTextView);
}
This looks much cleaner to me. I do not have to keep on creating inner Asynchronous tasks or create a separate class to run an Asynchronous task. If I want to have an Asynchtask that I reused in many activities then I would simply extend Asynch and override the Abstract methods and keep that as a separate class. Is their anything wrong with doing this? The only problem I see is that if I need to use two or more Asynchronous tasks in one activity.
As you have already pointed out you cannot have more than one asynchronous tasks in your activity. Apart from that your class can extend only one other class, not more.
So if you want an activity that extends ListActivity and has an asynchronous task you have to make another abstract asynch ("listActivityAsynch") class and so on.
The other thing is that your code is not easily understandable for other programmers by just looking at SomeActivity. They first have to look at Asynch and understand the uncommon design that you have used. If you are the only one who works with this code it is probably fine. But if others have to work with it it would be best to follow common android practice which is to make in inner class.

Categories