From b8c7f6ee4ee1672c0d60a097b5e203577fc9f9d3 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Wed, 5 Mar 2025 14:26:19 +0700 Subject: [PATCH 1/3] Convert LettersFragment file extension from .java to .kt --- .../ui/letter/{LettersFragment.java => LettersFragment.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/src/main/java/ai/elimu/content_provider/ui/letter/{LettersFragment.java => LettersFragment.kt} (100%) diff --git a/app/src/main/java/ai/elimu/content_provider/ui/letter/LettersFragment.java b/app/src/main/java/ai/elimu/content_provider/ui/letter/LettersFragment.kt similarity index 100% rename from app/src/main/java/ai/elimu/content_provider/ui/letter/LettersFragment.java rename to app/src/main/java/ai/elimu/content_provider/ui/letter/LettersFragment.kt From b0616993481bc2c41f041dac56ec91b40f987118 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Wed, 5 Mar 2025 14:30:43 +0700 Subject: [PATCH 2/3] Update LettersFragment from Java code to Kotlin --- .../ui/letter/LettersFragment.kt | 225 +++++++++--------- 1 file changed, 110 insertions(+), 115 deletions(-) diff --git a/app/src/main/java/ai/elimu/content_provider/ui/letter/LettersFragment.kt b/app/src/main/java/ai/elimu/content_provider/ui/letter/LettersFragment.kt index 4b45e168..588afb72 100644 --- a/app/src/main/java/ai/elimu/content_provider/ui/letter/LettersFragment.kt +++ b/app/src/main/java/ai/elimu/content_provider/ui/letter/LettersFragment.kt @@ -1,145 +1,140 @@ -package ai.elimu.content_provider.ui.letter; - -import android.os.Bundle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ProgressBar; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.Observer; -import androidx.lifecycle.ViewModelProvider; - -import com.google.android.material.snackbar.Snackbar; - -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import ai.elimu.content_provider.BaseApplication; -import ai.elimu.content_provider.R; -import ai.elimu.content_provider.rest.LettersService; -import ai.elimu.content_provider.room.GsonToRoomConverter; -import ai.elimu.content_provider.room.dao.LetterDao; -import ai.elimu.content_provider.room.db.RoomDb; -import ai.elimu.content_provider.room.entity.Letter; -import ai.elimu.model.v2.gson.content.LetterGson; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; -import retrofit2.Retrofit; - -public class LettersFragment extends Fragment { - - private LettersViewModel lettersViewModel; - - private ProgressBar progressBar; - - private TextView textView; - - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - Log.i(getClass().getName(), "onCreateView"); - - lettersViewModel = new ViewModelProvider(this).get(LettersViewModel.class); - View root = inflater.inflate(R.layout.fragment_letters, container, false); - progressBar = root.findViewById(R.id.progress_bar_letters); - textView = root.findViewById(R.id.text_letters); - lettersViewModel.getText().observe(getViewLifecycleOwner(), new Observer() { - @Override - public void onChanged(@Nullable String s) { - Log.i(getClass().getName(), "onChanged"); - textView.setText(s); +package ai.elimu.content_provider.ui.letter + +import ai.elimu.content_provider.BaseApplication +import ai.elimu.content_provider.R +import ai.elimu.content_provider.rest.LettersService +import ai.elimu.content_provider.room.GsonToRoomConverter +import ai.elimu.content_provider.room.db.RoomDb +import ai.elimu.model.v2.gson.content.LetterGson +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ProgressBar +import android.widget.TextView +import androidx.fragment.app.Fragment +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProvider +import com.google.android.material.snackbar.Snackbar +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response +import java.util.concurrent.Executors + +class LettersFragment : Fragment() { + private var lettersViewModel: LettersViewModel? = null + + private var progressBar: ProgressBar? = null + + private var textView: TextView? = null + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + Log.i(javaClass.name, "onCreateView") + + lettersViewModel = ViewModelProvider(this).get( + LettersViewModel::class.java + ) + val root = inflater.inflate(R.layout.fragment_letters, container, false) + progressBar = root.findViewById(R.id.progress_bar_letters) + textView = root.findViewById(R.id.text_letters) as? TextView + lettersViewModel!!.text.observe(viewLifecycleOwner, object : Observer { + override fun onChanged(s: String?) { + Log.i(javaClass.name, "onChanged") + textView?.text = s } - }); - return root; + }) + return root } - @Override - public void onStart() { - Log.i(getClass().getName(), "onStart"); - super.onStart(); + override fun onStart() { + Log.i(javaClass.name, "onStart") + super.onStart() // Download Letters from REST API, and store them in the database - BaseApplication baseApplication = (BaseApplication) getActivity().getApplication(); - Retrofit retrofit = baseApplication.getRetrofit(); - LettersService lettersService = retrofit.create(LettersService.class); - Call> letterGsonsCall = lettersService.listLetters(); - Log.i(getClass().getName(), "letterGsonsCall.request(): " + letterGsonsCall.request()); - letterGsonsCall.enqueue(new Callback>() { - - @Override - public void onResponse(Call> call, Response> response) { - Log.i(getClass().getName(), "onResponse"); - - Log.i(getClass().getName(), "response: " + response); - if (response.isSuccessful()) { - List letterGsons = response.body(); - Log.i(getClass().getName(), "letterGsons.size(): " + letterGsons.size()); - - if (letterGsons.size() > 0) { - processResponseBody(letterGsons); + val baseApplication = activity!!.application as BaseApplication + val retrofit = baseApplication.retrofit + val lettersService = retrofit.create(LettersService::class.java) + val letterGsonsCall = lettersService.listLetters() + Log.i(javaClass.name, "letterGsonsCall.request(): " + letterGsonsCall.request()) + letterGsonsCall.enqueue(object : Callback> { + override fun onResponse( + call: Call>, + response: Response> + ) { + Log.i(javaClass.name, "onResponse") + + Log.i(javaClass.name, "response: $response") + if (response.isSuccessful) { + val letterGsons = response.body()!! + Log.i(javaClass.name, "letterGsons.size(): " + letterGsons.size) + + if (letterGsons.size > 0) { + processResponseBody(letterGsons) } } else { // Handle error - Snackbar.make(textView, response.toString(), Snackbar.LENGTH_LONG) - .setBackgroundTint(getResources().getColor(R.color.deep_orange_darken_4)) - .show(); - progressBar.setVisibility(View.GONE); + Snackbar.make(textView!!, response.toString(), Snackbar.LENGTH_LONG) + .setBackgroundTint(resources.getColor(R.color.deep_orange_darken_4)) + .show() + progressBar!!.visibility = View.GONE } } - @Override - public void onFailure(Call> call, Throwable t) { - Log.e(getClass().getName(), "onFailure", t); + override fun onFailure(call: Call>, t: Throwable) { + Log.e(javaClass.name, "onFailure", t) - Log.e(getClass().getName(), "t.getCause():", t.getCause()); + Log.e(javaClass.name, "t.getCause():", t.cause) // Handle error - Snackbar.make(textView, t.getCause().toString(), Snackbar.LENGTH_LONG) - .setBackgroundTint(getResources().getColor(R.color.deep_orange_darken_4)) - .show(); - progressBar.setVisibility(View.GONE); + Snackbar.make(textView!!, t.cause.toString(), Snackbar.LENGTH_LONG) + .setBackgroundTint(resources.getColor(R.color.deep_orange_darken_4)) + .show() + progressBar!!.visibility = View.GONE } - }); + }) } - private void processResponseBody(List letterGsons) { - Log.i(getClass().getName(), "processResponseBody"); + private fun processResponseBody(letterGsons: List) { + Log.i(javaClass.name, "processResponseBody") - ExecutorService executorService = Executors.newSingleThreadExecutor(); - executorService.execute(new Runnable() { - @Override - public void run() { - Log.i(getClass().getName(), "run"); + val executorService = Executors.newSingleThreadExecutor() + executorService.execute(object : Runnable { + override fun run() { + Log.i(javaClass.name, "run") - RoomDb roomDb = RoomDb.getDatabase(getContext()); - LetterDao letterDao = roomDb.letterDao(); + val roomDb = RoomDb.getDatabase(context) + val letterDao = roomDb.letterDao() // Empty the database table before downloading up-to-date content - letterDao.deleteAll(); + letterDao.deleteAll() - for (LetterGson letterGson : letterGsons) { - Log.i(getClass().getName(), "letterGson.getId(): " + letterGson.getId()); + for (letterGson in letterGsons) { + Log.i(javaClass.name, "letterGson.getId(): " + letterGson.id) // Store the Letter in the database - Letter letter = GsonToRoomConverter.getLetter(letterGson); - letterDao.insert(letter); - Log.i(getClass().getName(), "Stored Letter in database with ID " + letter.getId()); + val letter = GsonToRoomConverter.getLetter(letterGson) + letterDao.insert(letter) + Log.i(javaClass.name, "Stored Letter in database with ID " + letter.id) } // Update the UI - List letters = letterDao.loadAllOrderedByUsageCount(); - Log.i(getClass().getName(), "letters.size(): " + letters.size()); - getActivity().runOnUiThread(() -> { - textView.setText("letters.size(): " + letters.size()); - Snackbar.make(textView, "letters.size(): " + letters.size(), Snackbar.LENGTH_LONG).show(); - progressBar.setVisibility(View.GONE); - }); + val letters = letterDao.loadAllOrderedByUsageCount() + Log.i(javaClass.name, "letters.size(): " + letters.size) + activity!!.runOnUiThread { + textView!!.text = "letters.size(): " + letters.size + Snackbar.make( + textView!!, + "letters.size(): " + letters.size, + Snackbar.LENGTH_LONG + ).show() + progressBar!!.visibility = View.GONE + } } - }); + }) } } From bef8a71f04d60f05f683d5efa19fb6c28ecbbea1 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Wed, 5 Mar 2025 14:32:30 +0700 Subject: [PATCH 3/3] Avoid repeatedly extracting log tag from class name in runtime --- .../ui/letter/LettersFragment.kt | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/ai/elimu/content_provider/ui/letter/LettersFragment.kt b/app/src/main/java/ai/elimu/content_provider/ui/letter/LettersFragment.kt index 588afb72..1f87bc41 100644 --- a/app/src/main/java/ai/elimu/content_provider/ui/letter/LettersFragment.kt +++ b/app/src/main/java/ai/elimu/content_provider/ui/letter/LettersFragment.kt @@ -29,12 +29,14 @@ class LettersFragment : Fragment() { private var textView: TextView? = null + private val TAG = javaClass.name + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { - Log.i(javaClass.name, "onCreateView") + Log.i(TAG, "onCreateView") lettersViewModel = ViewModelProvider(this).get( LettersViewModel::class.java @@ -44,7 +46,7 @@ class LettersFragment : Fragment() { textView = root.findViewById(R.id.text_letters) as? TextView lettersViewModel!!.text.observe(viewLifecycleOwner, object : Observer { override fun onChanged(s: String?) { - Log.i(javaClass.name, "onChanged") + Log.i(TAG, "onChanged") textView?.text = s } }) @@ -52,7 +54,7 @@ class LettersFragment : Fragment() { } override fun onStart() { - Log.i(javaClass.name, "onStart") + Log.i(TAG, "onStart") super.onStart() // Download Letters from REST API, and store them in the database @@ -60,18 +62,18 @@ class LettersFragment : Fragment() { val retrofit = baseApplication.retrofit val lettersService = retrofit.create(LettersService::class.java) val letterGsonsCall = lettersService.listLetters() - Log.i(javaClass.name, "letterGsonsCall.request(): " + letterGsonsCall.request()) + Log.i(TAG, "letterGsonsCall.request(): " + letterGsonsCall.request()) letterGsonsCall.enqueue(object : Callback> { override fun onResponse( call: Call>, response: Response> ) { - Log.i(javaClass.name, "onResponse") + Log.i(TAG, "onResponse") - Log.i(javaClass.name, "response: $response") + Log.i(TAG, "response: $response") if (response.isSuccessful) { val letterGsons = response.body()!! - Log.i(javaClass.name, "letterGsons.size(): " + letterGsons.size) + Log.i(TAG, "letterGsons.size(): " + letterGsons.size) if (letterGsons.size > 0) { processResponseBody(letterGsons) @@ -86,9 +88,9 @@ class LettersFragment : Fragment() { } override fun onFailure(call: Call>, t: Throwable) { - Log.e(javaClass.name, "onFailure", t) + Log.e(TAG, "onFailure", t) - Log.e(javaClass.name, "t.getCause():", t.cause) + Log.e(TAG, "t.getCause():", t.cause) // Handle error Snackbar.make(textView!!, t.cause.toString(), Snackbar.LENGTH_LONG) @@ -100,12 +102,12 @@ class LettersFragment : Fragment() { } private fun processResponseBody(letterGsons: List) { - Log.i(javaClass.name, "processResponseBody") + Log.i(TAG, "processResponseBody") val executorService = Executors.newSingleThreadExecutor() executorService.execute(object : Runnable { override fun run() { - Log.i(javaClass.name, "run") + Log.i(TAG, "run") val roomDb = RoomDb.getDatabase(context) val letterDao = roomDb.letterDao() @@ -114,17 +116,17 @@ class LettersFragment : Fragment() { letterDao.deleteAll() for (letterGson in letterGsons) { - Log.i(javaClass.name, "letterGson.getId(): " + letterGson.id) + Log.i(TAG, "letterGson.getId(): " + letterGson.id) // Store the Letter in the database val letter = GsonToRoomConverter.getLetter(letterGson) letterDao.insert(letter) - Log.i(javaClass.name, "Stored Letter in database with ID " + letter.id) + Log.i(TAG, "Stored Letter in database with ID " + letter.id) } // Update the UI val letters = letterDao.loadAllOrderedByUsageCount() - Log.i(javaClass.name, "letters.size(): " + letters.size) + Log.i(TAG, "letters.size(): " + letters.size) activity!!.runOnUiThread { textView!!.text = "letters.size(): " + letters.size Snackbar.make(