Skip to content

Instantly share code, notes, and snippets.

@codinginflow
Created July 28, 2021 20:41
Show Gist options
  • Save codinginflow/fbab20f953e00956689b3b519cc86989 to your computer and use it in GitHub Desktop.
Save codinginflow/fbab20f953e00956689b3b519cc86989 to your computer and use it in GitHub Desktop.
Architecture Components Beginner Tutorial Part 8
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
tools:context=".AddNoteActivity">
<EditText
android:id="@+id/edit_text_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Title"
android:inputType="text" />
<EditText
android:id="@+id/edit_text_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Description"
android:inputType="textMultiLine" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Priority:"
android:textAppearance="@android:style/TextAppearance.Medium" />
<NumberPicker
android:id="@+id/number_picker_priority"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="@layout/note_item" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/button_add_note"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="32dp"
android:src="@drawable/ic_add" />
</android.support.design.widget.CoordinatorLayout>
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/save_note"
android:icon="@drawable/ic_save"
android:title="Save"
app:showAsAction="ifRoom" />
</menu>
package com.codinginflow.architectureexample;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.EditText;
import android.widget.NumberPicker;
import android.widget.Toast;
public class AddNoteActivity extends AppCompatActivity {
public static final String EXTRA_TITLE =
"com.codinginflow.architectureexample.EXTRA_TITLE";
public static final String EXTRA_DESCRIPTION =
"com.codinginflow.architectureexample.EXTRA_DESCRIPTION";
public static final String EXTRA_PRIORITY =
"com.codinginflow.architectureexample.EXTRA_PRIORITY";
private EditText editTextTitle;
private EditText editTextDescription;
private NumberPicker numberPickerPriority;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_note);
editTextTitle = findViewById(R.id.edit_text_title);
editTextDescription = findViewById(R.id.edit_text_description);
numberPickerPriority = findViewById(R.id.number_picker_priority);
numberPickerPriority.setMinValue(1);
numberPickerPriority.setMaxValue(10);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_close);
setTitle("Add Note");
}
private void saveNote() {
String title = editTextTitle.getText().toString();
String description = editTextDescription.getText().toString();
int priority = numberPickerPriority.getValue();
if (title.trim().isEmpty() || description.trim().isEmpty()) {
Toast.makeText(this, "Please insert a title and description", Toast.LENGTH_SHORT).show();
return;
}
Intent data = new Intent();
data.putExtra(EXTRA_TITLE, title);
data.putExtra(EXTRA_DESCRIPTION, description);
data.putExtra(EXTRA_PRIORITY, priority);
setResult(RESULT_OK, data);
finish();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.add_note_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.save_note:
saveNote();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.codinginflow.architectureexample">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".AddNoteActivity"
android:parentActivityName=".MainActivity" />
</application>
</manifest>
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/delete_all_notes"
android:title="Delete all notes"
app:showAsAction="never" />
</menu>
package com.codinginflow.architectureexample;
import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import java.util.List;
public class MainActivity extends AppCompatActivity {
public static final int ADD_NOTE_REQUEST = 1;
private NoteViewModel noteViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FloatingActionButton buttonAddNote = findViewById(R.id.button_add_note);
buttonAddNote.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, AddNoteActivity.class);
startActivityForResult(intent, ADD_NOTE_REQUEST);
}
});
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
final NoteAdapter adapter = new NoteAdapter();
recyclerView.setAdapter(adapter);
noteViewModel = ViewModelProviders.of(this).get(NoteViewModel.class);
noteViewModel.getAllNotes().observe(this, new Observer<List<Note>>() {
@Override
public void onChanged(@Nullable List<Note> notes) {
adapter.setNotes(notes);
}
});
new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0,
ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
noteViewModel.delete(adapter.getNoteAt(viewHolder.getAdapterPosition()));
Toast.makeText(MainActivity.this, "Note deleted", Toast.LENGTH_SHORT).show();
}
}).attachToRecyclerView(recyclerView);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ADD_NOTE_REQUEST && resultCode == RESULT_OK) {
String title = data.getStringExtra(AddNoteActivity.EXTRA_TITLE);
String description = data.getStringExtra(AddNoteActivity.EXTRA_DESCRIPTION);
int priority = data.getIntExtra(AddNoteActivity.EXTRA_PRIORITY, 1);
Note note = new Note(title, description, priority);
noteViewModel.insert(note);
Toast.makeText(this, "Note saved", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Note not saved", Toast.LENGTH_SHORT).show();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.main_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.delete_all_notes:
noteViewModel.deleteAllNotes();
Toast.makeText(this, "All notes deleted", Toast.LENGTH_SHORT).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
package com.codinginflow.architectureexample;
import android.arch.persistence.room.Entity;
import android.arch.persistence.room.PrimaryKey;
@Entity(tableName = "note_table")
public class Note {
@PrimaryKey(autoGenerate = true)
private int id;
private String title;
private String description;
private int priority;
public Note(String title, String description, int priority) {
this.title = title;
this.description = description;
this.priority = priority;
}
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
public String getTitle() {
return title;
}
public String getDescription() {
return description;
}
public int getPriority() {
return priority;
}
}
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="@+id/text_view_priority"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:text="1"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
<TextView
android:id="@+id/text_view_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_toStartOf="@id/text_view_priority"
android:ellipsize="end"
android:maxLines="1"
android:text="Title"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
<TextView
android:id="@+id/text_view_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/text_view_title"
android:text="Description" />
</RelativeLayout>
</android.support.v7.widget.CardView>
package com.codinginflow.architectureexample;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class NoteAdapter extends RecyclerView.Adapter<NoteAdapter.NoteHolder> {
private List<Note> notes = new ArrayList<>();
@NonNull
@Override
public NoteHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.note_item, parent, false);
return new NoteHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull NoteHolder holder, int position) {
Note currentNote = notes.get(position);
holder.textViewTitle.setText(currentNote.getTitle());
holder.textViewDescription.setText(currentNote.getDescription());
holder.textViewPriority.setText(String.valueOf(currentNote.getPriority()));
}
@Override
public int getItemCount() {
return notes.size();
}
public void setNotes(List<Note> notes) {
this.notes = notes;
notifyDataSetChanged();
}
public Note getNoteAt(int position) {
return notes.get(position);
}
class NoteHolder extends RecyclerView.ViewHolder {
private TextView textViewTitle;
private TextView textViewDescription;
private TextView textViewPriority;
public NoteHolder(View itemView) {
super(itemView);
textViewTitle = itemView.findViewById(R.id.text_view_title);
textViewDescription = itemView.findViewById(R.id.text_view_description);
textViewPriority = itemView.findViewById(R.id.text_view_priority);
}
}
}
package com.codinginflow.architectureexample;
import android.arch.lifecycle.LiveData;
import android.arch.persistence.room.Dao;
import android.arch.persistence.room.Delete;
import android.arch.persistence.room.Insert;
import android.arch.persistence.room.Query;
import android.arch.persistence.room.Update;
import java.util.List;
@Dao
public interface NoteDao {
@Insert
void insert(Note note);
@Update
void update(Note note);
@Delete
void delete(Note note);
@Query("DELETE FROM note_table")
void deleteAllNotes();
@Query("SELECT * FROM note_table ORDER BY priority DESC")
LiveData<List<Note>> getAllNotes();
}
package com.codinginflow.architectureexample;
import android.arch.persistence.db.SupportSQLiteDatabase;
import android.arch.persistence.room.Database;
import android.arch.persistence.room.Room;
import android.arch.persistence.room.RoomDatabase;
import android.content.Context;
import android.os.AsyncTask;
import android.support.annotation.NonNull;
@Database(entities = {Note.class}, version = 1)
public abstract class NoteDatabase extends RoomDatabase {
private static NoteDatabase instance;
public abstract NoteDao noteDao();
public static synchronized NoteDatabase getInstance(Context context) {
if (instance == null) {
instance = Room.databaseBuilder(context.getApplicationContext(),
NoteDatabase.class, "note_database")
.fallbackToDestructiveMigration()
.addCallback(roomCallback)
.build();
}
return instance;
}
private static RoomDatabase.Callback roomCallback = new RoomDatabase.Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
new PopulateDbAsyncTask(instance).execute();
}
};
private static class PopulateDbAsyncTask extends AsyncTask<Void, Void, Void> {
private NoteDao noteDao;
private PopulateDbAsyncTask(NoteDatabase db) {
noteDao = db.noteDao();
}
@Override
protected Void doInBackground(Void... voids) {
noteDao.insert(new Note("Title 1", "Description 1", 1));
noteDao.insert(new Note("Title 2", "Description 2", 2));
noteDao.insert(new Note("Title 3", "Description 3", 3));
return null;
}
}
}
package com.codinginflow.architectureexample;
import android.app.Application;
import android.arch.lifecycle.LiveData;
import android.os.AsyncTask;
import java.util.List;
public class NoteRepository {
private NoteDao noteDao;
private LiveData<List<Note>> allNotes;
public NoteRepository(Application application) {
NoteDatabase database = NoteDatabase.getInstance(application);
noteDao = database.noteDao();
allNotes = noteDao.getAllNotes();
}
public void insert(Note note) {
new InsertNoteAsyncTask(noteDao).execute(note);
}
public void update(Note note) {
new UpdateNoteAsyncTask(noteDao).execute(note);
}
public void delete(Note note) {
new DeleteNoteAsyncTask(noteDao).execute(note);
}
public void deleteAllNotes() {
new DeleteAllNotesAsyncTask(noteDao).execute();
}
public LiveData<List<Note>> getAllNotes() {
return allNotes;
}
private static class InsertNoteAsyncTask extends AsyncTask<Note, Void, Void> {
private NoteDao noteDao;
private InsertNoteAsyncTask(NoteDao noteDao) {
this.noteDao = noteDao;
}
@Override
protected Void doInBackground(Note... notes) {
noteDao.insert(notes[0]);
return null;
}
}
private static class UpdateNoteAsyncTask extends AsyncTask<Note, Void, Void> {
private NoteDao noteDao;
private UpdateNoteAsyncTask(NoteDao noteDao) {
this.noteDao = noteDao;
}
@Override
protected Void doInBackground(Note... notes) {
noteDao.update(notes[0]);
return null;
}
}
private static class DeleteNoteAsyncTask extends AsyncTask<Note, Void, Void> {
private NoteDao noteDao;
private DeleteNoteAsyncTask(NoteDao noteDao) {
this.noteDao = noteDao;
}
@Override
protected Void doInBackground(Note... notes) {
noteDao.delete(notes[0]);
return null;
}
}
private static class DeleteAllNotesAsyncTask extends AsyncTask<Void, Void, Void> {
private NoteDao noteDao;
private DeleteAllNotesAsyncTask(NoteDao noteDao) {
this.noteDao = noteDao;
}
@Override
protected Void doInBackground(Void... voids) {
noteDao.deleteAllNotes();
return null;
}
}
}
package com.codinginflow.architectureexample;
import android.app.Application;
import android.arch.lifecycle.AndroidViewModel;
import android.arch.lifecycle.LiveData;
import android.support.annotation.NonNull;
import java.util.List;
public class NoteViewModel extends AndroidViewModel {
private NoteRepository repository;
private LiveData<List<Note>> allNotes;
public NoteViewModel(@NonNull Application application) {
super(application);
repository = new NoteRepository(application);
allNotes = repository.getAllNotes();
}
public void insert(Note note) {
repository.insert(note);
}
public void update(Note note) {
repository.update(note);
}
public void delete(Note note) {
repository.delete(note);
}
public void deleteAllNotes() {
repository.deleteAllNotes();
}
public LiveData<List<Note>> getAllNotes() {
return allNotes;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment