mirror of
https://github.com/nextcloud/notes-android.git
synced 2024-11-24 13:56:14 +03:00
refactor autosave: replace Timer by Handler
This commit is contained in:
parent
4529801fce
commit
7ead3f9e45
1 changed files with 93 additions and 102 deletions
|
@ -2,8 +2,9 @@ package it.niedermann.owncloud.notes.android.fragment;
|
|||
|
||||
import android.app.Fragment;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Editable;
|
||||
|
@ -11,21 +12,14 @@ import android.text.TextWatcher;
|
|||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.yydcdut.rxmarkdown.RxMDEditText;
|
||||
import com.yydcdut.rxmarkdown.RxMarkdown;
|
||||
import com.yydcdut.rxmarkdown.factory.EditFactory;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import it.niedermann.owncloud.notes.R;
|
||||
import it.niedermann.owncloud.notes.model.DBNote;
|
||||
import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
|
||||
|
@ -38,13 +32,16 @@ public class NoteEditFragment extends Fragment implements NoteFragmentI {
|
|||
public static final String PARAM_NOTE = "note";
|
||||
|
||||
private static final String LOG_TAG = "NoteEditFragment";
|
||||
private static final long DELAY = 2000; // in ms
|
||||
private static final long DELAY_AFTER_SYNC = 5000; // in ms
|
||||
private static final String LOG_TAG_AUTOSAVE = "AutoSave";
|
||||
|
||||
private static final long DELAY = 2000; // Wait for this time after typing before saving
|
||||
private static final long DELAY_AFTER_SYNC = 5000; // Wait for this time after saving before checking for next save
|
||||
private static final long DELAY_SHOW_SAVED = 1000; // How long "saved" is shown
|
||||
|
||||
private DBNote note;
|
||||
private Timer timer, timerNextSync;
|
||||
private boolean saveActive = false;
|
||||
private NoteSQLiteOpenHelper db;
|
||||
private Handler handler;
|
||||
private boolean saveActive, unsavedEdit;
|
||||
|
||||
public static NoteEditFragment newInstance(DBNote note) {
|
||||
NoteEditFragment f = new NoteEditFragment();
|
||||
|
@ -65,6 +62,7 @@ public class NoteEditFragment extends Fragment implements NoteFragmentI {
|
|||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setHasOptionsMenu(true);
|
||||
handler = new Handler(Looper.getMainLooper());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -109,61 +107,68 @@ public class NoteEditFragment extends Fragment implements NoteFragmentI {
|
|||
content.setText(charSequence, TextView.BufferType.SPANNABLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
content.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
private final TextWatcher textWatcher = new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(final CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(final Editable s) {
|
||||
unsavedEdit = true;
|
||||
if(!saveActive) {
|
||||
handler.removeCallbacks(runAutoSave);
|
||||
handler.postDelayed(runAutoSave, DELAY);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onTextChanged(final CharSequence s, int start, int before, int count) {
|
||||
if (timer != null) {
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(final Editable s) {
|
||||
if(timer != null) {
|
||||
timer.cancel();
|
||||
}
|
||||
if(!saveActive) {
|
||||
timer = new Timer();
|
||||
timer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(getActivity() != null)
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
autoSave();
|
||||
}
|
||||
});
|
||||
}
|
||||
}, DELAY);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
getContentView().addTextChangedListener(textWatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
getContentView().removeTextChangedListener(textWatcher);
|
||||
cancelTimers();
|
||||
}
|
||||
|
||||
private final Runnable runAutoSave = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(unsavedEdit) {
|
||||
Log.d(LOG_TAG_AUTOSAVE, "runAutoSave: start AutoSave");
|
||||
autoSave();
|
||||
} else {
|
||||
Log.d(LOG_TAG_AUTOSAVE, "runAutoSave: nothing changed");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable runResetActionBar = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ActionBar actionBar = getActionBar();
|
||||
if(actionBar == null) {
|
||||
Log.w(LOG_TAG_AUTOSAVE, "runResetActionBar: ActionBar NOT AVAILABLE!");
|
||||
return;
|
||||
}
|
||||
Log.d(LOG_TAG_AUTOSAVE, "runResetActionBar: reset action bar");
|
||||
actionBar.setSubtitle(getString(R.string.action_edit_editing));
|
||||
}
|
||||
};
|
||||
|
||||
private void cancelTimers() {
|
||||
if (timer != null) {
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
}
|
||||
if (timerNextSync != null) {
|
||||
timerNextSync.cancel();
|
||||
timerNextSync = null;
|
||||
}
|
||||
saveActive = false;
|
||||
handler.removeCallbacks(runAutoSave);
|
||||
handler.removeCallbacks(runResetActionBar);
|
||||
}
|
||||
|
||||
private RxMDEditText getContentView() {
|
||||
|
@ -176,20 +181,32 @@ public class NoteEditFragment extends Fragment implements NoteFragmentI {
|
|||
* @return String of the current content.
|
||||
*/
|
||||
private String getContent() {
|
||||
return ((EditText) getContentView()).getText().toString();
|
||||
return getContentView().getText().toString();
|
||||
}
|
||||
|
||||
private ActionBar getActionBar() {
|
||||
AppCompatActivity activity = (AppCompatActivity) getActivity();
|
||||
if(activity == null) {
|
||||
return null;
|
||||
}
|
||||
return activity.getSupportActionBar();
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the current changes and show the status in the ActionBar
|
||||
*/
|
||||
private void autoSave() {
|
||||
Log.d(LOG_TAG, "START save+sync");
|
||||
final ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
|
||||
Log.d(LOG_TAG_AUTOSAVE, "STARTAUTOSAVE");
|
||||
ActionBar actionBar = getActionBar();
|
||||
// if fragment is not attached to activity, then there is nothing to save
|
||||
if (getActivity() == null) {
|
||||
Log.w(LOG_TAG_AUTOSAVE, "autoSave: Activity NOT AVAILABLE!");
|
||||
return;
|
||||
}
|
||||
saveActive = true;
|
||||
if (actionBar != null) {
|
||||
actionBar.setSubtitle(getString(R.string.action_edit_saving));
|
||||
}
|
||||
final String content = getContent();
|
||||
saveData(new ICallback() {
|
||||
@Override
|
||||
public void onFinish() {
|
||||
|
@ -201,50 +218,23 @@ public class NoteEditFragment extends Fragment implements NoteFragmentI {
|
|||
onSaved();
|
||||
}
|
||||
|
||||
public void onSaved() {
|
||||
private void onSaved() {
|
||||
// AFTER SYNCHRONIZATION
|
||||
Log.d(LOG_TAG, "...sync finished");
|
||||
if (getActivity() != null && actionBar != null) {
|
||||
actionBar.setTitle(note.getTitle());
|
||||
actionBar.setSubtitle(getResources().getString(R.string.action_edit_saved));
|
||||
Executors.newSingleThreadScheduledExecutor().schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (getActivity() != null) {
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// AFTER 1 SECOND: set ActionBar to default title
|
||||
if (getActivity() != null && actionBar != null)
|
||||
actionBar.setSubtitle(getString(R.string.action_edit_editing));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}, 1, TimeUnit.SECONDS);
|
||||
|
||||
timerNextSync = new Timer();
|
||||
timerNextSync.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (getActivity() != null) {
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// AFTER "DELAY_AFTER_SYNC" SECONDS: allow next auto-save or start it directly
|
||||
if (getContent().equals(content)) {
|
||||
saveActive = false;
|
||||
Log.d(LOG_TAG, "FINISH, no new changes");
|
||||
} else {
|
||||
Log.d(LOG_TAG, "content has changed meanwhile -> restart save");
|
||||
autoSave();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}, DELAY_AFTER_SYNC);
|
||||
Log.d(LOG_TAG_AUTOSAVE, "FINISHED AUTOSAVE");
|
||||
saveActive = false;
|
||||
ActionBar actionBar = getActionBar();
|
||||
if (actionBar == null) {
|
||||
Log.w(LOG_TAG_AUTOSAVE, "autoSave/onSaved: ActionBar NOT AVAILABLE!");
|
||||
return;
|
||||
}
|
||||
actionBar.setTitle(note.getTitle());
|
||||
actionBar.setSubtitle(getResources().getString(R.string.action_edit_saved));
|
||||
|
||||
// AFTER "DELAY_SHOW_SAVED": set ActionBar to default title
|
||||
handler.postDelayed(runResetActionBar, DELAY_SHOW_SAVED);
|
||||
|
||||
// AFTER "DELAY_AFTER_SYNC" SECONDS: allow next auto-save or start it directly
|
||||
handler.postDelayed(runAutoSave, DELAY_AFTER_SYNC);
|
||||
|
||||
}
|
||||
});
|
||||
|
@ -253,10 +243,11 @@ public class NoteEditFragment extends Fragment implements NoteFragmentI {
|
|||
/**
|
||||
* Save the current state in the database and schedule synchronization if needed.
|
||||
*
|
||||
* @param callback
|
||||
* @param callback Observer which is called after save/synchronization
|
||||
*/
|
||||
private void saveData(ICallback callback) {
|
||||
Log.d(LOG_TAG, "saveData()");
|
||||
note = db.updateNoteAndSync(note, getContent(), callback);
|
||||
unsavedEdit = false;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue