I have a parent activity NavigationActivity and it does something like this:
public class NavigationActivity extends Activity {
protected LinearLayout navigationBar;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
navigationBar = findViewById(R.id.navbar);
}
}
It has one method that sets the visibility of navigationBar:
#Override
protected void setNavbarVisibility(int view) {
if (this.navigationBar != null) {
this.navigationBar.setVisibility(view);
}
}
I have an activity AdventureActivity that extends NavigationActivity:
public class AdventureActivity extends NavigationActivity {
EditText title;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstancState);
renderAdventureLayout();
}
public void renderAdventureLayout() {
Handler h = new Handler();
title.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(final View v, boolean hasFocus) {
if (hasFocus) {
h.postDelayed(new Runnable() {
#Override
public void run() {
setNavbarVisibility(View.GONE);
}
}, 200);
} else {
h.postDelayed(new Runnable() {
#Override
public void run() {
setNavbarVisibility(View.VISIBLE);
}
}, 200);
}
}
}
}
}
Now, I didn't have to declare or initialize navigationBar in AdventureActivity, and it's already initially visible. However, the statement setNavbarVisibility(View.GONE); doesn't seem to work in AdventureActivity unless I also initialize navigationBar as it was initialized in NavigationActivity because according the debugger, navigationBar was null when it wasn't initialized in AdventureActivity. I find it redundant having to initialize navigationBar in both activities.
You haven't provided a content view in either of your activities, which results findViewById() method to return null.
If you want to create such an activity hierarchy, that means, that NavigationActivity should have an abstract method, that subclasses should implement:
public abstract class NavigationActivity extends Activity {
...
#LayoutRes
protected abstract int getLayoutId();
}
Then AdventureActivity would become:
public class AdventureActivity extends NavigationActivity {
...
#Override
#LayoutRes
protected int getLayoutId() {
return R.layout.some_activity;
}
}
Now in NavigationActivity#onCreate():
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutId());
navigationBar = findViewById(R.id.navbar);
}
This mandates each of subclasses to provide a layout, where exists a LinearLayout with id navbar, otherwise your navigationBar would end up being null.
Related
I have a video player app where I need to access the lifecycle of an abstract activity from another class in Android. In my abstract activity, I've tried using LifecycleRegistry, but this is getting me the lifecycle owner not the actually lifecycle of the abstract class. How can I access the lifecycle of an abstract activity from another class?
Here is my abstract activity:
abstract public class MainActivity extends AppCompatActivity {
private LifecycleRegistry lifecycleRegistry;
VideoPlayer videoPlayer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
lifecycleRegistry = new LifecycleRegistry(this);
lifecycleRegistry.setCurrentState(Lifecycle.State.CREATED);
setContentView(R.layout.activity_main);
videoPlayer = new VideoPlayer();
playVideo();
}
public void playVideo(){
videoPlayer.init();
//calls function in VideoPlayer class
}
#Override
protected void onResume() {
super.onResume();
lifecycleRegistry.setCurrentState(Lifecycle.State.RESUMED);
}
#Override
protected void onDestroy() {
super.onDestroy();
lifecycleRegistry.setCurrentState(Lifecycle.State.DESTROYED);
}
}
Here is the class where I need to get the lifecycle of my abstract MainActivity:
public class VideoPlayer {
public void init() {
playVideo();
}
public void playVideo() {
//async call happens here, I need getLifeCycle() from MainActivity
}
}
Don't know a know about the context of you feature, but you You can do smth
public class VideoPlayer {
private Lifecycle mLifecycle;
public VideoPlayer(Lifecycle lifecycle) {
mLifecycle = lifecycle;
}
public void init() {
playVideo();
}
public void playVideo() {
//you have mLifecycle now
}
}
In Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
videoPlayer = new VideoPlayer(getLifecycle());
}
I am trying to understand better how to create a custom listener with a simple example but I don't know how to start the interface so that it is not null:
public class MainActivity extends AppCompatActivity implements ListenerButton{
TextView helloToOther;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
helloToOther = findViewById(R.id.helloWorldToOtherActivity);
helloToOther.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, ButtonActivity.class));
}
});
}
#Override
public void onClickButton(View view) {
Toast.makeText(this, "Estoy en la primera activity", Toast.LENGTH_SHORT).show();
}
}
This is the second activity:
public class ButtonActivity extends AppCompatActivity {
Button btnInterface;
ListenerButton listenerButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_button);
btnInterface = findViewById(R.id.button_activity__btn__button_interface);
setUpButtonInterface();
}
private void setUpButtonInterface() {
btnInterface.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listenerButton.onClickButton(v);
}
});
}
}
And there's the interface:
public interface ListenerButton {
void onClickButton(View view);
}
Basically I get a null pointer exception on the second activity because the interface is null, but I don't fall right now as I can start it. Thank you very much.
the reason you are getting a null pointer exception is because you haven't assigned anything to variable listenerButton and therefor it is in fact null!!
you don't need a new interface for that you just need to do this:
public class ButtonActivity extends AppCompatActivity {
Button btnInterface;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_button);
btnInterface = findViewById(R.id.button_activity__btn__button_interface);
setUpButtonInterface();
}
private void setUpButtonInterface() {
btnInterface.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//do whatever you want to do when button is clicked!
}
});
}
}
if you want to define whatever you want to do when button is clicked you need a class and not an interface:
public class ButtonListener implements View.OnClickListener{
#Override
public void onClick(View v) {
//do whatever you want to do when button is clicked!
}
}
and then in your activity do this:
public class ButtonActivity extends AppCompatActivity {
Button btnInterface;
ListenerButton listenerButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_button);
listenerButton = new ButtonListener();
btnInterface = findViewById(R.id.button_activity__btn__button_interface);
setUpButtonInterface();
}
private void setUpButtonInterface() {
btnInterface.setOnClickListener(listenerButton);
}
}
Create a new file:
MyListener.java:
public interface MyListener {
// you can define any parameter as per your requirement
public void callback(View view, String result);
}
In your activity, implement the interface:
MyActivity.java:
public class MyActivity extends Activity implements MyListener {
#override
public void onCreate(){
MyButton m = new MyButton(this);
}
// method is invoked when MyButton is clicked
#override
public void callback(View view, String result) {
// do your stuff here
}
}
In your custom class, invoke the interface when needed:
MyButton.java:
public class MyButton {
MyListener ml;
// constructor
MyButton(MyListener ml) {
//Setting the listener
this.ml = ml;
}
public void MyLogicToIntimateOthers() {
//Invoke the interface
ml.callback(this, "success");
}
}
I have an Activity that includes a TextView to display the current status of the app. Besides MainActivity there is another class that is used for checking for updates and then updating the app if appropriate.
This is the important part of the code.
public class MainActivity extends AppCompatActivity {
private TextView status;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
status = findViewById(R.id.status);
new Update().check();
}
public void setStatus(String status) {
this.status.setText(status);
}
}
How can I update the status TextView from within the Update class?
public class Update extends Activity {
public void check(final Context c) {
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView status = findViewById(R.id.status);
status.setText("Checking for updates...");
}
});
// final TextView status = getApplicationContext().findViewById(R.id.status);
// status.setText("Checking for updates");
// Check for updates...
}
public class UpdateApp extends AsyncTask<String,Void,Void> {
private Context context;
public void setContext(Context contextf){
context = contextf;
}
#Override
protected Void doInBackground(String... arg0) {
// Update the app
}
}
}
Attempting to run getApplicationContext().findViewById(R.id.status) crashes the app. When I put it in a try block it still crashes the app - how can that be when I catch a Throwable object? ... that doesn't make sense!!!
Using runOnUiThread the app runs but the status is not updated.
Put the UpdateApp AsynTask in new file.
public class MainActivity extends AppCompatActivity {
private TextView status;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
status = findViewById(R.id.status);
new UpdateApp(status).execute();
}
}
UpdateApp.java
public class UpdateApp extends AsyncTask<String,Void,Void> {
private TextView status;
public UpdateApp(TextView status){
this.status = status;
}
#Override
protected void onPostExecute(String result) {
status.setText("Update complete");
}
#Override
protected void onPreExecute() {
status.setText("Checking for updates...");
}
#Override
protected Void doInBackground(String... arg0) {
// Update the app
}
}
You just don't need another class to make it works, just copy your UpdateApp class inside MainActivity to access your status view.
In case you want your UpdateApp class to be in a different file (witch I recommend, to separate classes responsibility) you'd need a callback: a reference to your activity to update the status view from the AsyncTask class. The way you can make it is using Interfaces. Take a look to this example
MainActivity.java
public class MainActivity extends AppCompatActivity implements CallbackInterface {
private TextView status;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
status = findViewById(R.id.status);
new LoaderClass(this).execute();
}
#Override
public void setStatusText(String text) {
status.setText(text);
}
}
CallbackInterface.java
public interface CallbackInterface {
void setStatusText(String text);
}
LoaderClass.java
public class LoaderClass extends AsyncTask<String, Void, Void> {
private CallbackInterface callbackInterface;
public LoaderClass(CallbackInterface callback) {
callbackInterface = callback;
}
#Override
protected Void doInBackground(String... arg0) {
callbackInterface.setStatusText("Loaded text");
return null;
}
}
If you are in any Activity you can use runonUIthread() like -
runOnUiThread(new Runnable() {
#Override
public void run () {
// do your magic here
}
});
How call to this method OnClick? I really tried, but i'm noob for this.
getAdapterPosition its not possible? How to get this?
public class ViewActivity extends AppCompatActivity implements
android.view.View.OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
CheckBox buttonShare;
buttonShare = findViewById(R.id.button_shared);
buttonShare.setOnClickListener(this);
public void onClick(android.view.View v) {
switch (v.getId()) {
case R.id.button_shared:
shareWallpaper(wallpaperList.get(getAdapterPosition()));
break;
}
}
public void shareWallpaper(Wallpaper w) {
findViewById(R.id.progressbar).setVisibility(android.view.View.VISIBLE);
Glide.with(this)
.asBitmap()
.load(w.url)
.into(new SimpleTarget<Bitmap>() {
#Override
public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) {
#blabla
}
}
);
}
shareWallpaper(wallpaperList.get(getAdapterPosition()));
1) Solution for onClick method. change this
public class ViewActivity extends AppCompatActivity implements android.view.View.OnClickListener
to
public class ViewActivity extends AppCompatActivity
then in OnCreate method do
#Override
protected void onCreate(Bundle savedInstanceState) {
CheckBox buttonShare;
buttonShare = findViewById(R.id.button_shared);
buttonShare.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
shareWallpaper();
}
});
}
2) You cannot call getAdapterPosition() directly there is no such method.It's in the adapter class so do
adapter.getAdapterPosition();
How should I fetch value of a Checkbox which is in an Activity and in its onCreate there is findviewbyId method.
public class abc extends Activity {
Checkbox mon;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_xml);
mon = (CheckBox)findViewById(R.id.checkbox_mon);
}
public boolean check()
{
if (mon.isChecked())
return true;
else
return false;
}}
Now, there is another java class, in which I am passing the activity class object and calling that method which returns the value.
abc a =new abc();
a.check();
But it is not working. I think there is problem with findviewbyid statement.
And also, if the acitivity is not being opened , I want it to show the defualt value which I set in the xml file
android:checked="false"
Set a static variable and assign the value of CheckBox:
public class abc extends Activity {
Checkbox mon;
public static boolean checkBoxValue; //here
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_xml);
mon = (CheckBox)findViewById(R.id.checkbox_mon);
}
public boolean check()
{
if (mon.isChecked())
checkBoxValue = true; //here
return true;
else
checkBoxValue = false; //here
}}
Another class:
public class AnotherClass {
.....
public boolean value = abc.checkBoxValue;
.......
}
Another way
abc Activity:
public boolean check()
{
if (mon.isChecked())
Intent intent = new Intent(this, anotherClass.class);
intent.putExtra("value", true);
startActivity(intent);
return true;
.....
.......
another Activty:
public class AnotherClass extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.anotherclass);
boolean value = getIntent().getBooleanExtra("value");
}
}
Boolean with static modifier would be enough for your case.
public static boolean monValue = false // as you mention the default is false
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.my_xml);
mon = (CheckBox)findViewById(R.id.checkbox_mon);
mon.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener {
public void onCheckedChanged(CompoundButton btn, boolean b) {
monValue = b;
}
});
}
Then you just need to boolean x = abc.monValue in other class.
But I really want to suggest another way to communicate between class within android lifecycle.
With EventBus
Create class that wraps event data
public class MyCheckboxEvent {
public final boolean checked;
public MyCheckboxEvent(boolean checked) {
this.checked = checked;
}
}
Then add EventBus.getDefault().post(new MyCheckboxEvent(booleanValue)); on you abc activity
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.my_xml);
mon = (CheckBox)findViewById(R.id.checkbox_mon);
mon.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener {
public void onCheckedChanged(CompoundButton btn, boolean b) {
EventBus.getDefault().post(new MyCheckboxEvent(b));
}
});
}
Add the handler on any class that subscribe the abc Checkbox event data
#Subscribe
public void handleMyAbcCheckbox(MyCheckboxEvent event) {
boolean x = event.checked;
}
Then register and unregister the subscriber according to the lifecycle
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}