Reputation: 43
I need to create a login screen and a simple first screen (with a log out button). When a user logs in, for convenience, it does not require to log in again (only when the log out button is hit). To do this, i need to store a boolean variable whether the users is logged in or not.
When I hit the home button and open the app again, the app remembers that I already logged in. But when I hi the back button, it does not remember it.
Here is my code of the login screen:
package com.example.a20172425.login;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
public class LoginActivity extends AppCompatActivity {
EditText usernameEditText;
EditText passwordEditText;
TextView falseLoginTextView;
SharedPreferences pref;
boolean validCredentials = false;
public static Boolean login = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
usernameEditText = (EditText)findViewById(R.id.usernameField);
passwordEditText = (EditText)findViewById(R.id.passwordField);
falseLoginTextView = (TextView)findViewById(R.id.falseLoginText);
pref = getPreferences(MODE_PRIVATE);
login = getLoginStatus();
if(login) {
toMainActivity();
}
}
public void checkCredentials(View v){
//clear possible previous content
falseLoginTextView.setText("");
//retrieve username and password
String username = usernameEditText.getText().toString();
String password = passwordEditText.getText().toString();
if ((username.equals("username")) && (password.equals("password"))) {
validCredentials = true;
setLoginStatus(true);
//setUsername(username);
} else if ((username.equals("a")) && (password.equals("a"))) {
validCredentials = true;
setLoginStatus(true);
//setUsername(username);
}
if (validCredentials){
toMainActivity();
}
else
{
falseLoginTextView.setText("Incorrect username and or password");
}
}
public void toMainActivity(){
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.putExtra("Username", usernameEditText.getText().toString());
this.startActivity(intent);
//makes sure pressing the back button does not send the app back to the login screen
this.finish();
}
// gets the logged_in value from persistent memory.
public Boolean getLoginStatus (){
return pref.getBoolean("Logged_in",false);
}
//sets the logged_in boolean value in persistent memory.
public void setLoginStatus(Boolean loginStatus){
//editor to change values to be stored in memory
SharedPreferences.Editor edit = pref.edit();
edit.putBoolean("Logged_in",loginStatus);
//save changes
edit.commit();
}
}
This is my code of the simple first screen:
package com.example.a20172425.login;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import static com.example.a20172425.login.LoginActivity.login;
public class MainActivity extends AppCompatActivity {
TextView LoginTextView;
LoginActivity loginActivity;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LoginTextView = (TextView) findViewById(R.id.LoginTV);
String username = getIntent().getStringExtra("Username");
LoginTextView.setText("Currently logged in as: " + username);
loginActivity = new LoginActivity();
}
public void toLoginActivity(View v) {
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
this.startActivity(intent);
login = false;
//loginActivity.setLogin(false);
//makes sure pressing the back button does not send the app back to the login screen
this.finish();
}
}
Any suggestion will be appreciated.
Upvotes: 0
Views: 66
Reputation: 4853
EDIT: I write Kotlin in my day to day job, I didn't actually compile the Java examples below so there may be some syntactical errors. However, it should be fairly trivial to resolve these with basic working Java knowledge. The concepts in this answer are applicable to the vast majority of OO languages (Kotlin, Java, C# etc.).
I'm updating this answer to give some more detail on what an interface is, why they are useful, how callbacks work and how they are implemented under the hood.
In object oriented programming (OO) and, in this case, Java; there is a type system that allows for polymorphism. Polymorphism, when broken down, means (poly -> many) and (morphism -> behaving like), or, in other words, many similarly behaving different types.
What these means in more concrete coding terms is that you can have many different classes of types which conform to a common behaviour (or interface). The behaviour of a type should be thought of as it's outwardly observable behaviours and not the internal implementation. It is useful to conceptualise this with respect to the type system. For example, a behaviour is defined as a transformation from one type to another (for instance a function that takes a collection of strings and returns a string). There are many functions that could perform this transformation, but the outwardly observable behaviour of all of these functions is the same (in other words, a transformation Collection -> String).
It therefore follows that such a type system can allow for arbitrary swapping of implementations as long as the outwardly observable behaviour is maintained.
Interfaces are a popular language construct to achieve this. An interface merely defines the tranformations between types and gives them names. Other types may then depend on this interface and call methods of this interface without any concern as to the actual implementation of the methods (the only constraint being that the implementors of said interface must conform to the type transformations - this is enforced at compile time in Java).
Here is a very simple interface:
public interface Car {
public Int accelerate(Int force);
public Int steer(Int direction);
}
I use the car example as it's quite intuitive. Here we can see two type transformations, from Int -> Int
with a name accelerate
, and from Int -> Int
with a name of steer
.
All cars can accelerate
and steer
. But not all cars accelerate
and steer
in the same way. However, all cars steer
and accelerate
behaviours follow a common pattern (or type transformation). They take some input value and result in some output value.
So, we could provide several implementations of car like so (bear in mind this is a very contrived example, so don't judge):
public class Ford implements Car {
@Override
public Int accelerate(Int force) {
return force * 1;
}
@Override
public Int steer(Int direction) {
return direction * 1;
}
}
public class Ferrari implements Car {
@Override
public Int accelerate(Int force) {
return force * 10;
}
@Override
public Int steer(Int direction) {
return direction * 10;
}
}
As you can see, a Ford and Ferrari both steer and accelerate. But the Ferrari does it differently (but it still conforms to the type transformation just as the Ford does).
Now, here we introduce polymorphism, which is a very powerful tool. Imagine we have the following class:
public class Person {
private Car car;
public Person(Car car) {
this.car = car
}
}
So, a person can be constructed by passing a car as a dependancy to it. Due to polymorphism we can pass any instance of an object that implements (or conforms to) the Car interface. For instance, we could do the following:
public class Main {
public void main([String] args) {
Person poorPerson = new Person(new Ford());
Person richPerson = new Person(new Ferrari());
}
}
Pretty nifty! Now we can create hundreds of different types of cars but our person class never has to change! Our person class can call methods on their respectively owned cars and never have to worry about anything breaking (because all cars can accelerate and steer).
So, how does this relate to the original question? Let us consider this very contrived example of an Android View class and a Callback interface:
public interface ContrivedCallback {
public void onClick();
}
public class ContrivedView {
private ContrivedCallback callback;
public void setOnClickListener(ContrivedCallback: callback) {
this.callback = callback;
}
private void onClick() {
this.callback.invoke();
}
}
Let us assume that the onClick
method in the ContrivedView
class is magically called by the Android OS when the view is clicked. Now, when the view is clicked, the callback (if set) is invoked. But, as we now know, the callback is just an interface, so whatever implementation was provided to the setCallback
method will be invoked.
So, the callbacks single defined method is merely a transformation from Void -> Void (in other words, it takes no arguments and returns no value). It's just some code to run. The implementation may launch rockets, save to a database, print a string or do literally nothing, it's up to the coder providing the implementation).
I hope this makes sense? Now, with respect to the original question:
You can use an onClickListener callback. In this callback implementation you can write some code that updates some state of the Activity or Fragment (or write to preferences or local database, or launch missiles... you get the picture).
You create an implementation and then assign this implementation to the callback listener on the button in question like so (in your onCreate method):
logoutButton = (Button)findViewById(R.id.logoutButton);
logoutButton.addOnClickListener(class callback extends DialogInterface.OnClickListener {
@Override
public void onClick() {
// Do stuff here...
}
});
Upvotes: 1