Skip to content

Commit ddabe0c

Browse files
Merge pull request #92 from MihaiCristianCondrea/codex/create-roomactivity-with-note-entity-and-dao
Add Room database lesson with basic CRUD demo
2 parents 2cad84d + af6c8c8 commit ddabe0c

File tree

42 files changed

+680
-10
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+680
-10
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
- **Minor**: Added a search function for lessons.
88
- **Patch**: Optimized app performance for smoother operation.
99
- **Patch**: Updated several components to improve compatibility.
10+
- **New**: Added a Room database lesson demonstrating entity, DAO, and code viewer integration.
1011

1112
# Version 5.0.1:
1213

app/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ dependencies {
9696
implementation libs.codeview
9797
implementation libs.hilt.android
9898
annotationProcessor libs.hilt.compiler
99+
implementation libs.androidx.room.runtime
100+
annotationProcessor libs.androidx.room.compiler
99101

100102
// Testing
101103
testImplementation libs.junit

app/src/main/AndroidManifest.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,18 @@
304304
android:label="@string/navigation_drawer"
305305
android:parentActivityName=".ui.screens.main.MainActivity" />
306306

307+
<activity
308+
android:name=".ui.screens.android.lessons.data.room.RoomActivity"
309+
android:exported="false"
310+
android:label="@string/room_database"
311+
android:parentActivityName=".ui.screens.main.MainActivity" />
312+
313+
<activity
314+
android:name=".ui.screens.android.lessons.data.room.RoomCodeActivity"
315+
android:exported="false"
316+
android:label="@string/room_database"
317+
android:parentActivityName=".ui.screens.android.lessons.data.room.RoomActivity" />
318+
307319
<activity
308320
android:name=".ui.screens.settings.SettingsActivity"
309321
android:exported="false"
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.d4rk.androidtutorials.java.ui.screens.android.lessons.data.room;
2+
3+
import android.content.Context;
4+
5+
import androidx.room.Database;
6+
import androidx.room.Room;
7+
import androidx.room.RoomDatabase;
8+
9+
/**
10+
* The Room database that holds the notes.
11+
*/
12+
@Database(entities = {Note.class}, version = 1, exportSchema = false)
13+
public abstract class AppDatabase extends RoomDatabase {
14+
private static volatile AppDatabase INSTANCE;
15+
16+
public abstract NoteDao noteDao();
17+
18+
public static AppDatabase getInstance(Context context) {
19+
if (INSTANCE == null) {
20+
synchronized (AppDatabase.class) {
21+
if (INSTANCE == null) {
22+
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
23+
AppDatabase.class, "notes_db").build();
24+
}
25+
}
26+
}
27+
return INSTANCE;
28+
}
29+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.d4rk.androidtutorials.java.ui.screens.android.lessons.data.room;
2+
3+
import androidx.room.Entity;
4+
import androidx.room.PrimaryKey;
5+
6+
/**
7+
* Simple Note entity stored in the Room database.
8+
*/
9+
@Entity(tableName = "notes")
10+
public class Note {
11+
@PrimaryKey(autoGenerate = true)
12+
public int id;
13+
public String text;
14+
15+
public Note(String text) {
16+
this.text = text;
17+
}
18+
19+
public String getText() {
20+
return text;
21+
}
22+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.d4rk.androidtutorials.java.ui.screens.android.lessons.data.room;
2+
3+
import androidx.room.Dao;
4+
import androidx.room.Insert;
5+
import androidx.room.Query;
6+
7+
import java.util.List;
8+
9+
/**
10+
* Data Access Object for {@link Note}.
11+
*/
12+
@Dao
13+
public interface NoteDao {
14+
@Insert
15+
void insert(Note note);
16+
17+
@Query("SELECT * FROM notes")
18+
List<Note> getAll();
19+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package com.d4rk.androidtutorials.java.ui.screens.android.lessons.data.room;
2+
3+
import android.content.Intent;
4+
import android.os.Bundle;
5+
import android.os.Handler;
6+
import android.view.LayoutInflater;
7+
import android.view.View;
8+
import android.view.ViewGroup;
9+
10+
import androidx.annotation.NonNull;
11+
import androidx.recyclerview.widget.LinearLayoutManager;
12+
import androidx.recyclerview.widget.RecyclerView;
13+
14+
import com.d4rk.androidtutorials.java.R;
15+
import com.d4rk.androidtutorials.java.databinding.ActivityRoomBinding;
16+
import com.d4rk.androidtutorials.java.ui.components.navigation.UpNavigationActivity;
17+
import com.d4rk.androidtutorials.java.utils.EdgeToEdgeDelegate;
18+
import com.google.android.material.textview.MaterialTextView;
19+
20+
import java.util.ArrayList;
21+
import java.util.List;
22+
import java.util.concurrent.ExecutorService;
23+
import java.util.concurrent.Executors;
24+
25+
/**
26+
* Demonstrates basic Room usage by inserting and reading notes.
27+
*/
28+
public class RoomActivity extends UpNavigationActivity {
29+
private final Handler handler = new Handler();
30+
private ActivityRoomBinding binding;
31+
private NotesAdapter adapter;
32+
private AppDatabase db;
33+
private final ExecutorService executor = Executors.newSingleThreadExecutor();
34+
35+
@Override
36+
protected void onCreate(Bundle savedInstanceState) {
37+
super.onCreate(savedInstanceState);
38+
binding = ActivityRoomBinding.inflate(getLayoutInflater());
39+
setContentView(binding.getRoot());
40+
41+
EdgeToEdgeDelegate edgeToEdgeDelegate = new EdgeToEdgeDelegate(this);
42+
edgeToEdgeDelegate.applyEdgeToEdge(binding.constraintLayout);
43+
44+
db = AppDatabase.getInstance(this);
45+
46+
binding.recyclerView.setLayoutManager(new LinearLayoutManager(this));
47+
adapter = new NotesAdapter();
48+
binding.recyclerView.setAdapter(adapter);
49+
50+
loadNotes();
51+
52+
binding.buttonAdd.setOnClickListener(v -> {
53+
String text = String.valueOf(binding.editTextNote.getText()).trim();
54+
if (!text.isEmpty()) {
55+
executor.execute(() -> {
56+
db.noteDao().insert(new Note(text));
57+
runOnUiThread(() -> {
58+
binding.editTextNote.setText("");
59+
loadNotes();
60+
});
61+
});
62+
}
63+
});
64+
65+
binding.floatingButtonShowSyntax.setOnClickListener(v ->
66+
startActivity(new Intent(RoomActivity.this, RoomCodeActivity.class)));
67+
handler.postDelayed(() -> binding.floatingButtonShowSyntax.shrink(), 5000);
68+
}
69+
70+
private void loadNotes() {
71+
executor.execute(() -> {
72+
List<Note> notes = db.noteDao().getAll();
73+
runOnUiThread(() -> adapter.setNotes(notes));
74+
});
75+
}
76+
77+
private static class NotesAdapter extends RecyclerView.Adapter<NotesAdapter.NoteViewHolder> {
78+
private List<Note> notes = new ArrayList<>();
79+
80+
void setNotes(List<Note> notes) {
81+
this.notes = notes;
82+
notifyDataSetChanged();
83+
}
84+
85+
@NonNull
86+
@Override
87+
public NoteViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
88+
View view = LayoutInflater.from(parent.getContext())
89+
.inflate(R.layout.item_note, parent, false);
90+
return new NoteViewHolder(view);
91+
}
92+
93+
@Override
94+
public void onBindViewHolder(@NonNull NoteViewHolder holder, int position) {
95+
holder.textView.setText(notes.get(position).getText());
96+
}
97+
98+
@Override
99+
public int getItemCount() {
100+
return notes.size();
101+
}
102+
103+
static class NoteViewHolder extends RecyclerView.ViewHolder {
104+
final MaterialTextView textView;
105+
106+
NoteViewHolder(View itemView) {
107+
super(itemView);
108+
textView = itemView.findViewById(R.id.textViewNote);
109+
}
110+
}
111+
}
112+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package com.d4rk.androidtutorials.java.ui.screens.android.lessons.data.room;
2+
3+
import android.os.Bundle;
4+
5+
import androidx.annotation.NonNull;
6+
import androidx.annotation.Nullable;
7+
import androidx.fragment.app.Fragment;
8+
import androidx.viewpager2.adapter.FragmentStateAdapter;
9+
10+
import com.d4rk.androidtutorials.java.R;
11+
import com.d4rk.androidtutorials.java.databinding.ActivityTabLayoutBinding;
12+
import com.d4rk.androidtutorials.java.ui.components.navigation.UpNavigationActivity;
13+
import com.d4rk.androidtutorials.java.ui.screens.android.lessons.data.room.tabs.RoomTabCodeFragment;
14+
import com.d4rk.androidtutorials.java.ui.screens.android.lessons.data.room.tabs.RoomTabLayoutFragment;
15+
import com.d4rk.androidtutorials.java.utils.EdgeToEdgeDelegate;
16+
import com.google.android.material.tabs.TabLayoutMediator;
17+
18+
import java.util.ArrayList;
19+
20+
/**
21+
* Displays Java and XML snippets for the Room database example.
22+
*/
23+
public class RoomCodeActivity extends UpNavigationActivity {
24+
private ActivityTabLayoutBinding binding;
25+
26+
@Override
27+
protected void onCreate(@Nullable Bundle savedInstanceState) {
28+
super.onCreate(savedInstanceState);
29+
binding = ActivityTabLayoutBinding.inflate(getLayoutInflater());
30+
setContentView(binding.getRoot());
31+
32+
EdgeToEdgeDelegate edgeToEdgeDelegate = new EdgeToEdgeDelegate(this);
33+
edgeToEdgeDelegate.applyEdgeToEdge(binding.appBarLayout);
34+
35+
setupViewPager();
36+
37+
new TabLayoutMediator(binding.tabs, binding.viewpager, (tab, position) -> {
38+
ViewPagerAdapter adapter = (ViewPagerAdapter) binding.viewpager.getAdapter();
39+
if (adapter != null) {
40+
tab.setText(adapter.getPageTitle(position));
41+
}
42+
}).attach();
43+
}
44+
45+
private void setupViewPager() {
46+
ViewPagerAdapter adapter = new ViewPagerAdapter(this);
47+
adapter.addFragment(new RoomTabCodeFragment(), getString(R.string.code_java));
48+
adapter.addFragment(new RoomTabLayoutFragment(), getString(R.string.layout_xml));
49+
binding.viewpager.setAdapter(adapter);
50+
}
51+
52+
private static class ViewPagerAdapter extends FragmentStateAdapter {
53+
private final ArrayList<Fragment> fragmentList = new ArrayList<>();
54+
private final ArrayList<String> fragmentTitleList = new ArrayList<>();
55+
56+
ViewPagerAdapter(@NonNull UpNavigationActivity activity) {
57+
super(activity);
58+
}
59+
60+
void addFragment(@NonNull Fragment fragment, @NonNull String title) {
61+
fragmentList.add(fragment);
62+
fragmentTitleList.add(title);
63+
}
64+
65+
@NonNull
66+
@Override
67+
public Fragment createFragment(int position) {
68+
return fragmentList.get(position);
69+
}
70+
71+
@Override
72+
public int getItemCount() {
73+
return fragmentList.size();
74+
}
75+
76+
CharSequence getPageTitle(int position) {
77+
return fragmentTitleList.get(position);
78+
}
79+
}
80+
}
81+
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.d4rk.androidtutorials.java.ui.screens.android.lessons.data.room.tabs;
2+
3+
import android.content.SharedPreferences;
4+
import android.graphics.Typeface;
5+
import android.os.Bundle;
6+
import android.util.Log;
7+
import android.view.LayoutInflater;
8+
import android.view.View;
9+
import android.view.ViewGroup;
10+
11+
import androidx.annotation.NonNull;
12+
import androidx.fragment.app.Fragment;
13+
import androidx.preference.PreferenceManager;
14+
15+
import com.d4rk.androidtutorials.java.R;
16+
import com.d4rk.androidtutorials.java.databinding.FragmentCodeBinding;
17+
import com.d4rk.androidtutorials.java.utils.CodeHighlighter;
18+
import com.d4rk.androidtutorials.java.utils.CodeViewUtils;
19+
import com.d4rk.androidtutorials.java.utils.FontManager;
20+
import com.google.android.gms.ads.AdRequest;
21+
22+
import java.io.BufferedReader;
23+
import java.io.IOException;
24+
import java.io.InputStream;
25+
import java.io.InputStreamReader;
26+
27+
import me.zhanghai.android.fastscroll.FastScrollerBuilder;
28+
29+
/**
30+
* Shows the Java implementation for the Room example.
31+
*/
32+
public class RoomTabCodeFragment extends Fragment {
33+
34+
@Override
35+
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
36+
FragmentCodeBinding binding = FragmentCodeBinding.inflate(inflater, container, false);
37+
new FastScrollerBuilder(binding.scrollView).useMd2Style().build();
38+
binding.adView.loadAd(new AdRequest.Builder().build());
39+
40+
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(requireContext());
41+
Typeface monospaceFont = FontManager.getMonospaceFont(requireContext(), prefs);
42+
CodeViewUtils.applyDefaults(monospaceFont, binding.codeView);
43+
44+
StringBuilder builder = new StringBuilder();
45+
InputStream inputStream = getResources().openRawResource(R.raw.text_room_java);
46+
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
47+
String line;
48+
while ((line = reader.readLine()) != null) {
49+
builder.append(line).append('\n');
50+
}
51+
binding.codeView.setText(builder.toString());
52+
CodeHighlighter.applyJavaTheme(binding.codeView);
53+
} catch (IOException e) {
54+
Log.e("RoomTabCode", "Error reading code", e);
55+
}
56+
return binding.getRoot();
57+
}
58+
}
59+

0 commit comments

Comments
 (0)