This question already has answers here:
How can I change language of whole application by only single click?
(3 answers)
Closed 2 years ago.
I want to change the Language of Application through strings.
here is my string folders
I want to change the Language of Application through strings.
So here is from my side. its works perfectly for me.
Follow these steps to change Language.
1.Save your strings in folder like values-ur(URDU)
than convert your all strings to that language you have to convert
2.Make a BaseActivity class and extend all your rest Activities to that Base class
public class BaseActivity extends AppCompatActivity
{
public BaseActivity context;
public MySharePreference mySharePreference;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
context = BaseActivity.this;
mySharePreference = MySharePreference.getInstance(context);
LocaleHelper.setLocale(context, mySharePreference.getLanguage() );
}
protected void attachBaseContext(Context base)
{
super.attachBaseContext(LocaleHelper.onAttach(base));
}
}
3.I have ExampleActivity that i want to translate its language.
public class ExampleActivity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example);
}
}
simply extend your application to your BaseActivity class.
3.Make a LocalHelper class in which it change the direction and strings.
public class LocaleHelper
{
public static Context setLocale(Context context, String language)
{
Locale locale = new Locale(language);
Locale.setDefault(locale);
Resources resources = context.getResources();
Configuration configuration = new Configuration(resources.getConfiguration());
configuration.setLayoutDirection(locale);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
{
configuration.setLocale(locale);
LocaleList localeList = new LocaleList(locale);
LocaleList.setDefault(localeList);
configuration.setLocales(localeList);
}
else
{
configuration.locale = locale;
configuration.setLocale(locale);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1)
{
return context.createConfigurationContext(configuration);
}
else
{
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return context;
}
}
public static Context onAttach(Context context)
{
return setLocale(context, MySharePreference.getInstance(context).getLanguage());
}
}
4.In your App class attach base context
public class AppClass extends MultiDexApplication
{
private static AppClass appClass;
public static AppClass getintance()
{
return appClass;
}
#Override
public void onCreate()
{
super.onCreate();
appClass = this;
MySharePreference.getInstance(this);
}
#Override
protected void attachBaseContext(Context base)
{
super.attachBaseContext(LocaleHelper.onAttach(base));
}
}
5.In your build.gradle file add latest androidx SharedPreferences dependency.
implementation 'androidx.preference:preference:1.1.1'
6.In my case i make my Own SharedPreferences class.
public class MySharePreference
{
private static MySharePreference instance;
private static SharedPreferences pref;
private MySharePreference(Context context)
{
if (context != null)
{
pref = PreferenceManager.getDefaultSharedPreferences(context);
}
else
{
pref = PreferenceManager.getDefaultSharedPreferences(App.getintance());
}
}
public static MySharePreference getInstance(Context context)
{
if (instance == null || pref == null)
{
instance = new MySharePreference(context);
}
return instance;
}
public String getLanguage()
{
return pref.getString("appLanguage", "en");
}
public void setLanguage(String b)
{
pref.edit().putString("appLanguage", b).apply();
}
}
7.At last save the abbreviation of that language to SharedPreferences in my case i have spinner.
spinner_lang.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
{
if (mySharePreference.getLanguagePosition() != position)
{
mySharePreference.setLanguage(Constants.COUNTRY_LIST.get(position).countryAbbr);
mySharePreference.setLanguagePosition(position);
startActivity(new Intent(mActivity, MainActivity.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
}
}
#Override
public void onNothingSelected(AdapterView<?> parent)
{
}
});
now all done......
Related
I created a day/night mode switch system in my app. Currently, I use a PreferenceFragmentCompat + SharedPreference to display and save the switch selection.
This is my code:
public class PreferencesActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_preferences);
PreferencesFragment preferencesFragment = new PreferencesFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.preferences_container, preferencesFragment).commit();
}
public static class PreferencesFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener {
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.preferences, rootKey);
}
#Override
public void onResume() {
super.onResume();
getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (isAdded()) {
if (sharedPreferences.getBoolean(getString(R.string.KEY_PREF_NIGHT_MODE), false)) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
}
}
}
}
}
On top of that, I use the following code in the OnCreate method of my main Activity:
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
int mode = sharedPreferences.getBoolean(getString(R.string.KEY_PREF_NIGHT_MODE), false) ? AppCompatDelegate.MODE_NIGHT_YES : AppCompatDelegate.MODE_NIGHT_NO;
if (AppCompatDelegate.getDefaultNightMode() != mode)
AppCompatDelegate.setDefaultNightMode(mode);
The problem is that when I activate the dark mode and I restart the application, it will launch then restart in the onCreate. Isn't there a more optimal way to implement this system?
you could create BaseActivity where you set the night mode
abstract class BaseActivity extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY);
}
}
and then extend all your Activites from BaseActivity
public class PreferencesActivity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
}
}
then your night mode would be set in every activity before setContentView and no relaunch would be occured
UPDATE
change
#Override
public void onResume() {
super.onResume();
getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
to
#Override
public void onStart() {
super.onStart();
getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
onStart is called before view is visible
UPDATE 2
here is the singleton to access SharedPreferences
public class SharedManager {
private static SharedManager instance;
private final SharedPreferences preferences;
private SharedManager() {
preferences = MyApplication.getAppContext().getSharedPreferences(Constants.PREF_NAME, Context.MODE_PRIVATE);
}
public static SharedManager getInstance() {
if (instance == null) {
synchronized (SharedManager.class) {
if (instance == null) {
instance = new SharedManager();
}
}
}
return instance;
}
public SharedPreferences getPreferences() {
return preferences;
}
}
with call SharedManager.getInstance().getPreferences() you can get access to Preferences
I am trying to implement my own EditTextPreferenceDialogFragmentCompat. I would like to check if the user enter an IP address in the text field. If it's not the case, the user should not be able to validate the dialog. I have successfully shown my custom PreferenceDialogFragmentCompat, but I cannot save the text value anymore!
public class SettingsActivity extends AppCompatActivity {
public static final String PREF_IP_KEY = "ipDs1242_2";
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/*
...
*/
getSupportFragmentManager().beginTransaction().replace(android.R.id.content, new Preferences()).commit();
}
//A Fragment needs to be a public static class
public static class Preferences extends PreferenceFragmentCompat {
private EditTextPreference mIpModulePref;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e(getClass().getSimpleName(), "onCreate() frag Prefrences");
}
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.preferences_app);
Log.e(getClass().getSimpleName(), "onCreateFragment()");
mIpModulePref = findPreference(PREF_IP_KEY);
mIpModulePref.setSummary("Addresse IP : " + mIpModulePref.getText());
mIpModulePref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
Log.e(getClass().getSimpleName(), "new pref saved"); //never called...
return true;
}
});
mIpModulePref.setOnBindEditTextListener(this);
}
//shows my custom dialog
#Override
public void onDisplayPreferenceDialog(Preference preference) {
if (getFragmentManager().findFragmentByTag(DialogPreferenceFragment.TAG) != null) {
return;
}
if (preference instanceof EditTextPreference && preference.getKey().equals(PREF_IP_KEY)) {
DialogPreferenceFragment dialogPreferenceFragment = DialogPreferenceFragment.newInstance(PREF_IP_KEY);
dialogPreferenceFragment.setTargetFragment(this, DialogPreferenceFragment.REQUEST_CODE);
dialogPreferenceFragment.show(getFragmentManager(), DialogPreferenceFragment.TAG);
} else {
super.onDisplayPreferenceDialog(preference);
}
}
}
//the custom dialog to show
public static class DialogPreferenceFragment extends EditTextPreferenceDialogFragmentCompat {
public static final int REQUEST_CODE = 0;
public static final String TAG = "DialogPreferenceFragment_tag";
private Context mContext;
private EditTextPreference mEditTextPreference;
private SharedPreferences prefs;
public static DialogPreferenceFragment newInstance(String key){
Bundle bundle = new Bundle();
bundle.putString(ARG_KEY, key);
DialogPreferenceFragment dialogPreferenceFragment = new DialogPreferenceFragment();
dialogPreferenceFragment.setArguments(bundle);
return dialogPreferenceFragment;
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
mContext = context;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
}
#Override
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
Log.e(getClass().getSimpleName(), "restore pref IP");
mEditTextPreference = ((EditTextPreference) getPreference());
String txtValue = prefs.getString(mEditTextPreference.getKey(), ""); //reads the right value
mEditTextPreference.setText(txtValue);
}
#Override
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
super.onPrepareDialogBuilder(builder);
builder.setMessage("Enter the IP address");
}
#Override
public void onDialogClosed(boolean positiveResult) {
if(positiveResult){
Log.e(getClass().getSimpleName(), "save pref IP");
SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(mContext).edit();
editor.putString(mEditTextPreference.getKey(), mEditTextPreference.getText());
editor.commit();
String value = prefs.getString(mEditTextPreference.getKey(), ""); //DOESN'T SAVE THE VALUE !
Log.e(getClass().getSimpleName(), value);
}
}
}
}
I can read the right value in the the onBindDialogView() function, but I cannot save my value.
Do you have an idea of what I missed?
Thank you for your help.
I have a custom class which has a unique interface
public class CalculatorDialog extends Dialog implements OnClickListener {
TextView mView;
CalculatorListener delegate = null;
public CalculatorDialog (Context context, CalculatorListener delegate) {
this.context = context;
this.delegate = delegate;
}
public interface CalculatorListener extends OnClickListener {
#Override void onClick(View v);
}
#Override void onCreate(Bundle bundle) {
...
mView = (TextView) findViewById(...);
findViewbyId(...Button...).setOnClickListener(delegate);
}
public String getViewText() {
mView.getText().toString();
}
When creating new object of CalculatorDialog I want to implement my own action for clicking Button, but I want to get some String from a visible text view.
So in my MainActivity I try to do this:
CalculatorDialog dialogBox = new CalculatorDialog(context, new CalculatorDialog.CalculatorListener() {}
#Override
public void onClick(View v) {
String test = getViewText();
}
});
But as you and I have thought it can't be accessed from there.
Code here is not 1:1 with what I have in my project, but I think it represenets my needs. Also I have wrote it directly on StackOverflow, so it may contain some code bugs.
How can I access this function?
You should change your CalculatorListener
public class CalculatorDialog extends Dialog implements OnClickListener {
TextView mView;
CalculatorListener delegate = null;
public CalculatorDialog (Context context, CalculatorListener delegate) {
this.context = context;
this.delegate = delegate;
}
public interface CalculatorListener{
void onClick(View v, String text);
}
#Override void onCreate(Bundle bundle) {
...
mView = (TextView) findViewById(...);
findViewbyId(...Button...).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
delegate.onClick(view, getViewText());
});
}
public String getViewText() {
mView.getText().toString();
}
and
CalculatorDialog dialogBox = new CalculatorDialog(context, new CalculatorDialog.CalculatorListener() {}
#Override
public void onClick(View v, String text) {
String test = text;
}
I try to use Loaders instead AsyncTask.I can not figure out how to correctly organize the conservation status when the screen is rotated. I receive information from Json and trying create list.
public class FragmentWeatherTestApplication extends Fragment
implements LoaderManager.LoaderCallbacks<List<WeatherItem>> {
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
getLoaderManager().initLoader(0,null,this).forceLoad();
}
...
#Override
public Loader<List<WeatherItem>> onCreateLoader(int id, Bundle args) {
Log.i(TAG, "onCreateLoader");
return new FetchWeatherLoader(getActivity());
}
#Override
public void onLoadFinished(Loader<List<WeatherItem>> loader, List<WeatherItem> data) {
Log.i(TAG, "onLoadFinished");
mItems = data;
setupAdapter();
}
#Override
public void onLoaderReset(Loader<List<WeatherItem>> loader) {
Log.i(TAG, "onLoaderReset");
}
....
private static class FetchWeatherLoader extends AsyncTaskLoader<List<WeatherItem>>{
public FetchWeatherLoader(Context context) {
super(context);
}
#Override
public List<WeatherItem> loadInBackground() {
return new OpenWeatherFetch().fetchItems();
}
}
I want to convert my project according to MVP structure, & I had done it but it violate the MVP design, as it holds the activity instance in the presenter layer.
So, I just wanted to know how can I convert this project into pure MVP. Here Validation class is recursive and validate many fields & for here it is just for signup, and I had put the Validate method into separate thread.
This is my MVP interface
import android.app.Activity;
public class IMVP_Login {
/**
* View mandatory methods. Available to Presenter
* Presenter -> View
*/
public interface RequiredViewOps {
void showToast(String msg);
}
/**
* Operations offered from Presenter to View
* View -> Presenter
*/
public interface PresenterOps{
void submit(Activity activity);
}
}
This is my presenter with thread and containing the activity instance, which is against the design pattern of MVP, the code is as follows
import android.app.Activity;
import java.lang.ref.WeakReference;
import cp.utility.CustomException;
import cp.utility.Validation;
public class PresenterLogin implements Runnable,IMVP_Login.PresenterOps
{
private WeakReference<IMVP_Login.RequiredViewOps> mView;
// this is against the architectural law of MVP
private WeakReference<Activity> activity;
public PresenterLogin(IMVP_Login.RequiredViewOps mView) {
this.mView = new WeakReference<>(mView);
}
#Override
public void run() {
try
{
Validation.validate(activity.get());
}catch (CustomException e)
{
mView.get().showToast(e.getMessage());
}
}
//how should i do this with MVP PATTERN,as it is holding the activity instance
#Override
public void submit(Activity activity) {
this.activity=new WeakReference<>(activity);
Thread validationThread = new Thread(this,"Validation");
validationThread.start();
}
}
This is my activity,
public class Login extends AppCompatActivity implements View.OnClickListener,IMVP_Login.RequiredViewOps
{
private TextInputEditText edPhone,edCountrycode,edPassword;
private IMVP_Login.PresenterOps presenterLogin;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signin);
initialize();
}
private void initialize()
{
presenterLogin= new PresenterLogin(this);
Button btSignIn=GeneralFunction.findViewByIdAndCast(this,R.id.btnSignIn);
btSignIn.setOnClickListener(this);
edCountrycode = GeneralFunction.findViewByIdAndCast(this, R.id.etCode);
edPhone = GeneralFunction.findViewByIdAndCast(this, R.id.etPhone);
edPassword = GeneralFunction.findViewByIdAndCast(this, R.id.etPassword);
edPassword.setTypeface(Typekit.getInstance().get(getString(R.string.str_regular)));
edPassword.setTransformationMethod(new PasswordTransformationMethod());
}
#Override
public void onClick(View view) {
switch (view.getId())
{
case R.id.btnSignIn:
presenterLogin.submit(this);
break;
}
}
#Override
public void showToast(String msg) {
//show toast
}
}
This is the validation class depending on tag of editext,
public class Validation {
public static boolean validateFields(final ViewGroup parentView) throws CustomException
{
for (int i = 0; i < parentView.getChildCount(); i++)
{
if (parentView.getChildAt(i) instanceof ViewGroup) {
if ((parentView.getChildAt(i)).getVisibility() == View.VISIBLE)
validateFields((ViewGroup) parentView.getChildAt(i));
}
else if((parentView.getChildAt(i) instanceof TextView) && ((parentView.getChildAt(i)).getVisibility() == View.VISIBLE))
{
TextView editText = (TextView) parentView.getChildAt(i);
if(null!=editText.getTag())
{
String type = editText.getTag().toString().toLowerCase();
String text=GeneralFunction.getTextFromView(editText);
//validation depending on tag
}
}
}
return true;
}
public static boolean validate(Activity activity) {
final ViewGroup viewGroup = (ViewGroup) activity.findViewById(android.R.id.content);
return validateFields(viewGroup);
}
}
Let me start by saying that there are many different ways of doing MVP, each of them valid in their own right. The important things to keep in mind are:
The View should not know about the model, it doesn't care at all where its data is coming from.
The Presenter should not know about Android. You should be able to run your Presenter class entirely on the JVM.
Your Activity/Fragment/ViewGroup should implement the View interface which is how the Presenter communicates with them.
Why do we do this?
Separation of concerns.
You can change the network library you use in your Model and the View/Presenter should just work still. You could switch your View from a horizontal ViewPager to a vertical RecyclerView and the Presenter/Model equally wouldn't care.
Testing.
We can mock our Presenter and unit test the View or Model. Mock the View & Model and unit test the Presenter.
As long as the implementation of MVP that you are using allows the above then in my mind it is valid.
Onto your specific problem. I would set it up something like this:
View:
public interface LoginView {
Map<String,String> getLoginFields();
}
Activity:
public class LoginActivity extends AppCompatActivity implements LoginView {
private EditText emailView;
private EditText phoneView;
private EditText passwordView;
private Button loginView;
private LoginPresenter presenter;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
presenter = new LoginPresenter();
presenter.bindView(this);
emailView = findViewById(R.id.login_email);
phoneView = findViewById(R.id.login_phone);
passwordView = findViewById(R.id.login_password);
loginView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
presenter.login();
}
});
}
#Override
protected void onDestroy() {
presenter.unbindView();
super.onDestroy();
}
#Override
public Map<String, String> getLoginFields() {
Map<String, String> fields = new HashMap<>();
fields.put(emailView.getTag().toString(), emailView.getText().toString());
fields.put(phoneView.getTag().toString(), phoneView.getText().toString());
fields.put(passwordView.getTag().toString(), passwordView.getText().toString());
return fields;
}
}
You may wish to do something fancy with the getLoginFields method and loop through your container. Even if you had 100 fields though it shouldn't require offloading onto another thread. I'd be a very upset user if I had to fill out 100 fields...
Presenter:
public class LoginPresenter {
private LoginView view;
private LoginValidator validator;
public void bindView(LoginView view) {
this.view = view;
}
public void unbindView() {
view = null;
}
public void login() {
validator = new LoginValidator();
Map<String, String> fields = view.getLoginFields();
boolean isValid = validator.validate(fields);
}
}
Validator:
public class LoginValidator {
public boolean validate(Map<String, String> fields) {
//validation depending on tag
return true;
}
}
Threading
If the need does arise to process something on another thread in the Activity then you have several approaches you could take:
Pass a listener to the getLoginFields() method which gets called when the work is done.
Expose another method in the Presenter, something like onLoginFieldsProcessed which would get called once the work is done.
Have getLoginFields() return Observable (RxJava) or Future.
I would personally probably use RxJava, especially if I was already using it in the app.
The main reason why there is separate presenter class added in this MVP framework ( especially in android ) is to remove the OutOfMemory or if by chance the activity fails the presenter calls is not affected i.e why there is MVP approach followed instead of MV framework.
Consider the below example that is from below link :-
public class MainActivity extends Activity {
public static final String DEFAULT_NAME = "Chuck Norris";
private ArrayAdapter<ServerAPI.Item> adapter;
private Subscription subscription;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView)findViewById(R.id.listView);
listView.setAdapter(adapter = new ArrayAdapter<>(this, R.layout.item));
requestItems(DEFAULT_NAME);
}
#Override
protected void onDestroy() {
super.onDestroy();
unsubscribe();
}
public void requestItems(String name) {
unsubscribe();
subscription = App.getServerAPI()
.getItems(name.split("\\s+")[0], name.split("\\s+")[1])
.delay(1, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<ServerAPI.Response>() {
#Override
public void call(ServerAPI.Response response) {
onItemsNext(response.items);
}
}, new Action1<Throwable>() {
#Override
public void call(Throwable error) {
onItemsError(error);
}
});
}
public void onItemsNext(ServerAPI.Item[] items) {
adapter.clear();
adapter.addAll(items);
}
public void onItemsError(Throwable throwable) {
Toast.makeText(this, throwable.getMessage(), Toast.LENGTH_LONG).show();
}
private void unsubscribe() {
if (subscription != null) {
subscription.unsubscribe();
subscription = null;
}
}
}
In the above example the activity failure causes the presenter layer to stop working .Similarly ,if there is any object associated with this activity class ( View ) will be affected .
Referencing by static will make the activity die out while there is a crash but the presenter class will not be affected.( Please refer to below code for MVP ).
public class MainPresenter {
public static final String DEFAULT_NAME = "Chuck Norris";
private ServerAPI.Item[] items;
private Throwable error;
private MainActivity view;
public MainPresenter() {
App.getServerAPI()
.getItems(DEFAULT_NAME.split("\\s+")[0], DEFAULT_NAME.split("\\s+")[1])
.delay(1, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<ServerAPI.Response>() {
#Override
public void call(ServerAPI.Response response) {
items = response.items;
publish();
}
}, new Action1<Throwable>() {
#Override
public void call(Throwable throwable) {
error = throwable;
publish();
}
});
}
public void onTakeView(MainActivity view) {
this.view = view;
publish();
}
private void publish() {
if (view != null) {
if (items != null)
view.onItemsNext(items);
else if (error != null)
view.onItemsError(error);
}
}
}
public class MainActivity extends Activity {
private ArrayAdapter<ServerAPI.Item> adapter;
private static MainPresenter presenter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView)findViewById(R.id.listView);
listView.setAdapter(adapter = new ArrayAdapter<>(this, R.layout.item));
if (presenter == null)
presenter = new MainPresenter();
presenter.onTakeView(this);
}
#Override
protected void onDestroy() {
super.onDestroy();
presenter.onTakeView(null);
if (!isChangingConfigurations())
presenter = null;
}
public void onItemsNext(ServerAPI.Item[] items) {
adapter.clear();
adapter.addAll(items);
}
public void onItemsError(Throwable throwable) {
Toast.makeText(this, throwable.getMessage(), Toast.LENGTH_LONG).show();
}
}
MainActivity creates MainPresenter and keeps it outside of reach of onCreate/onDestroy cycle. MainActivity uses a static variable to reference MainPresenter, so every time a process restarts due to out-of-memory event, MainActivity should check if the presenter is still here and create it if needed.( As stated in the doc ).
Hope this helps :)