Is there a standard set of Listener/Observer/Observable classes in Android for managing application events in Android?
I'm not talking about UI or other Android API events, but rather custom app events like GameOverEvent, LevelClearedEvent, etc.
Is there a preferred interface to implement/extend so that I can implement things like:
public void addGameOverListener(GameOverListener listener)
It's easy,, you just need to create your own EventListener
public interface onGameFinishedListener {
public void onGameFinished(GameView gameView);
}
and some class which has onGameFinished() method
public abstract class GameView extends SurfaceView implements SurfaceHolder.Callback{
List<onGameFinishedListener> listeners;
public GameThread gameThread;
protected int width;
protected int height;
public GameView(Context context) {
super(context);
width = 320;
height = 480;
listeners = new ArrayList<onGameFinishedListener>();
}
public abstract void init();
public void registerGameFinishedListener(onGameFinishedListener listener) {
listeners.add(listener);
}
protected void GameFinished(GameView gameView) {
for (onGameFinishedListener listener : listeners) {
synchronized(gameThread.getSurfaceHolder()) {
listener.onGameFinished(gameView);
}
}
}
}
and then you implement the onGameFinishedListener in your activity or view which you want to do operation when the game finish,
public class RocketActivity extends GameActivity implements onGameFinishedListener {
private final int MENU = 0;
private final int END = 1;
private final int CONFIRMATION = 2;
private RelativeLayout layout;
private RocketView rocketView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
layout = new RelativeLayout(this);
rocketView = new RocketView(this);
rocketView.registerGameFinishedListener(this);
rocketView.init();
layout.addView(rocketView);
setContentView(layout);
}
#Override
public void onGameFinished(GameView gameView) {
runOnUiThread(new Runnable() {
#Override
public void run() {
showDialog(END);
}
});
}
}
there. no need to rely on Android for EventListener. :)
Have you tried EventBus by GreenRobot?
It is basically a pretty standard implementation of an eventBus for handling application wide events.
It provides inter-thread communication which is quite neat.
Pretty similar to what you get for GWT
Related
I am having trouble, measuring the height and width of a programatically created LinearLayout in android studio, I adopted the following solution
Public class MainActivity extends AppCompatActivity {
private static final String TAG = "MyActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final LinearLayout layout = new LinearLayout(context.this);
layout.post(new Runnable() {
#Override
public void run() {
int width = layout.getWidth();
int height = layout.getHeight();
}
}
}
the problem I am having is that I cant retrieve the value of these variables outside the override method. I have tried creating separate variables outside the override method like this
final LinearLayout layout = new LinearLayout(context.this);
final int width;
final int height;
layout.post(new Runnable() {
#Override
public void run() {
width = layout.getWidth();
height = layout.getHeight();
}
}
Log.d(TAG, "width is "+ width.ToString())
but even in this case width = 0 if called outside the override method. So my question is, is there a way to pass the value of variables outside an override method or is there a different way of measuring the height/width of a layout when it is called in an onCreate method
Declare Both width and height outside onCreate method
public class MainActivity extends AppCompatActivity {
int width;
int height;
private static final String TAG = "MyActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final LinearLayout layout = new LinearLayout(context.this);
layout.post(new Runnable() {
#Override
public void run() {
width = layout.getWidth();
height = layout.getHeight();
}
});
}
}
I am building a custom component in Java and trying to display that in React Native but the component is not appearing. I've been looking through forums and documentation for solutions but can't find a solution. I am not sure if it's an issue on the native side or the React Native side. Any help or advice on improvement is highly appreciated.
Bottom Sheet View
public class BottomSheetView extends NestedScrollView {
private BottomSheetBehavior bSheetBehavior;
public BottomSheetView(Context context) {
super(context);
init();
}
private void init() {
inflate(getContext(), R.layout.bottom_sheet, this);
CoordinatorLayout coordinaterLayout = findViewById(R.id.coordinate_layout);
View bottomSheet = coordinaterLayout.findViewById(R.id.bottom_sheet_component);
bSheetBehavior = BottomSheetBehavior.from(bottomSheet);
bSheetBehavior.setHideable(false);
bSheetBehavior.setPeekHeight((int) PixelUtil.toPixelFromDIP(200));
}
#Override
protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
}
}
Bottom Sheet Manager
public class BottomSheetManager extends ViewGroupManager<BottomSheetView> {
public static final String REACT_CLASS = "BottomSheet";
private BottomSheetView bottomSheet;
#Override
public String getName() {
return REACT_CLASS;
}
#Override
protected BottomSheetView createViewInstance(ThemedReactContext reactContext) {
return new BottomSheetView(reactContext);
}
}
Bottom Sheet Package
public class BottomSheetPackage implements ReactPackage {
private Activity mActivity = null;
BottomSheetPackage(Activity activity) {
mActivity = activity;
}
public BottomSheetPackage() {
}
#Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = Collections.emptyList();
return modules;
}
#Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Arrays.<ViewManager>asList(new BottomSheetManager());
}
}
React Native
class BottomSheet extends Component {
render() {
return (<BottomSheet style={{height: 200}}/>);
}
}
I'm setting up my first Vaadin application with Vaadin 7.5.6 and the official Vaadin Spring 1.0.0. I want to use the MVP pattern but I'm asking myself how the components work together. Because I'm new to MVP i don't want to use any Addons, so i tried to set it up by myself.
So if I'm right, the LoginViewPresenter will give me the view over presenterInstance.getView(). This is already working fine, but how should i access to the presenter over the view? When i want to do a logic operation for my view i should do it in the presenter class. But how to call a presenter method from a view Buttonclicklistener?
My second question is if I have the UIScope annotation over my presenter class, when does Spring instantiate a new object from this class? I thougt as long as the UI exists. But after generating a random string in the constructor I'm printing out the content of the randomString variable (in the UI.class init() method) but there is always a new value.
Regards
LoginViewPresenter.java
#SpringComponent
#UIScope
public class LoginViewPresenter implements Serializable
{
private static final long serialVersionUID = 6286518141570430211L;
#Autowired
private LoginView view;
public final String randomString;
public LoginViewPresenter()
{
randomString = Utils.generateRandomString(8);
}
#PostConstruct
public void init()
{
}
public LoginView getView()
{
return view;
}
public void setView(LoginView view)
{
this.view = view;
}
}
LoginView.java
#SuppressWarnings("serial")
#UIScope
#SpringView(name = LoginView.NAME)
public class LoginView extends VerticalLayout implements View
{
public static final String NAME = "LoginView";
#PostConstruct
private void init()
{
}
#Override
public void enter(ViewChangeEvent event)
{
}
}
Your view should'nt be aware of the presenter. It should fire events, and your presenter can listen to them.
Here is how I do it:
LoginView.java
#SuppressWarnings("serial")
#UIScope
#SpringView(name = LoginView.NAME)
public class LoginView extends VerticalLayout implements View {
public static final String NAME = "LoginView";
#Autowired
private transient Collection<LoginViewListener> loginViewListeners;
#PostConstruct
private void init() {
...
Button b = new Button("click me");
b.addClickListener(e -> loginViewListeners.forEach(l -> l.eventFired()));
addComponent(b);
...
loginViewListeners.forEach(listener -> listener.viewInitialized(this));
}
#Override
public void enter(ViewChangeEvent event)
{
}
public interface LoginViewListener {
void viewInitialized(LoginView view);
void eventFired();
}
}
LoginViewPresenter.java
#SpringComponent
#UIScope
public class LoginViewPresenter implements LoginViewListener, Serializable {
private static final long serialVersionUID = 6286518141570430211L;
private LoginView view;
public final String randomString;
public LoginViewPresenter() {
randomString = Utils.generateRandomString(8);
}
#PostConstruct
public void init() {
}
public LoginView getView() {
return view;
}
public void setView(LoginView view) {
this.view = view;
}
#Override
public void viewInitialized(LoginView v) {
setView(v);
}
#Override
void eventFired() {
...
}
}
Does your randomString still have always a new value with this design?
I would like to set up a button that would allow me to move to another activity while I finished drawing my painting.
The question is I don't know how to set up this button in the view class because it doesn't listen to any listeners.
In your drawing view, define your interface
public class MyDrawingView extends View
{
protected MyPaintingListener m_paintingListener;
public interface MyPaintingListener
{
// you can define any parameter as per your requirement
public void paintingEnded();
}
public void onCreateView()
{
// Create your view
}
public void draw()
{
// Draw your painting
// then
if(m_paintingListener != null)
m_paintingListener.paintingEnded();
}
public void setListener(MyPaintingListener p_listener)
{
m_paintingListener = p_listener;
}
}
In your current Fragment or Activity:
public class MyActivity extends Activity
implements MyDrawingView.MyPaintingListener
{
protected MyDrawingView m_drawingView;
public void OnActivityCreated(Bundle savedInstanceState)
{
// In this method or another, create your drawingView
m_drawingView = new MyDrawingView();
m_drawingView.setListener(this);
m_drawingView.paint();
}
#Override
public void paintingEnded()
{
// Set up your button;
}
}
I think I am making a design error in my Android app somewhere. My (simplified) code is pasted below.
I am using the writeMidi method in MainActivity. However, I would also like to use it, or actually just trigger it, when "onItemSelected" is triggered in the custom listener.
I am a bit torn on how to do that. Should I redesign this code to fit the customlistener in the main activity?
Thanks for any help.
public class MainActivity extends Activity{
int song = 0;
int[] music;
public int instrument;
public CustomOnItemSelectedListener listener;
// *******************************************************
// set Layout - on create
// *******************************************************
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
instrument = 0;
listener = new CustomOnItemSelectedListener();
addListenerOnSpinnerItemSelection();
//more stuff, including using the writeMidi method
};
public void addListenerOnSpinnerItemSelection(){
instrumentSp = (Spinner) findViewById(R.id.instrument);
instrumentSp.setOnItemSelectedListener(listener);
}
public void writeMidi(int[] music, int count) {
// so some stff
}
}
and in a separate file;
public class CustomOnItemSelectedListener implements OnItemSelectedListener {
private int instrument = 0;
public void onItemSelected(AdapterView<?> parent, View view, int pos,long id) {
Toast.makeText(parent.getContext(),
"Please wait a minute for the instrument to be changed. ", Toast.LENGTH_SHORT).show();
instrument = pos;
}
public int getInstrument(){
return instrument;
}
}
Use broadcast receiver in main class and send different type of broadcast(Different messages) to activate different methods in main activity.
You could create a Listener interface 'InstrumentSelectedListener', or something like that. Then have your MainActivity implement that interface, register it as a listener on your CustomOnItemSelectedListener, and fire a 'writeMidiNow' event in your onItemSelected.
You would end up with something like:
public class MainActivity extends Activity implements OnInstrumentSelectedListener{
int song = 0;
int[] music;
public int instrument;
public CustomOnItemSelectedListener listener;
// *******************************************************
// set Layout - on create
// *******************************************************
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
instrument = 0;
listener = new CustomOnItemSelectedListener();
addListenerOnSpinnerItemSelection();
//more stuff, including using the writeMidi method
};
public void addListenerOnSpinnerItemSelection(){
instrumentSp = (Spinner) findViewById(R.id.instrument);
instrumentSp.setOnItemSelectedListener(listener);
}
public void onInstrumentSelected(int instrument) {
// do some stuff with the instrument.
}
public void writeMidi(int[] music, int count) {
// so some stff
}
}
And
public class CustomOnItemSelectedListener implements OnItemSelectedListener {
public interface OnInstrumentSelectedListener{
public void onInstrumentSelected(int instrument);
}
private int instrument = 0;
private OnInstrumentSelectedListener instrumentlistener;
public void onItemSelected(AdapterView<?> parent, View view, int pos,long id) {
Toast.makeText(parent.getContext(),
"Please wait a minute for the instrument to be changed. ", Toast.LENGTH_SHORT).show();
instrument = pos;
if(instrumentListener != null)
instrumentListener.onInstrumentSelected(instrument);
}
public void setInstrumentListener(OnInstrumentSelectedListener listener) {
this.instrumentListener = listener;
}
public int getInstrument(){
return instrument;
}
}
2 ways to do it:
- First will be passing the context of MainActivity class to CustomOnItemSelectedListener class.
- Second way is quick and dirty, make the writeMidi() method as static, but you should keep in mind that static methods can access only static members, Not non-static members.
I tried a number of the solutions suggested, but could get none of them to fully work.
So I solved it by not using a separate class like this:
instrumentSp.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int pos,long id) {