4 ms·
>Like I was interviewing a guy for an Android role, and he was walking me through a pet project of his which consisted of literally one list view which updated
by ohgodplsno 6y ago
>Like I was interviewing a guy for an Android role, and he was walking me through a pet project of his which consisted of literally one list view which updated it's contents to filter results out of an SQLite database as you type into a text field, and the project had literally dozens of files. It just made me sad.
That's most likely overengineering. The only things you need for this are:
- An Activity
- Eventually, a Fragment, but you can do your work in the activity directly
- A database, optionally in another file to abstract out direct queries, but it can simply be direct SupportSQLite queries. Just, not on the main thread.
- A viewmodel if you don't want to hate yourself and write logic in your Activity, making it basically untestable.
- A layout file for your activity/fragment.
- A layout file for your recyclerview list element
That's 5 files. 6 if you include build.gradle, 7 with AndroidManifest.xml
This can all be written in under 500 total lines.
Library wise, all you need for that is androidx and recyclerview.
- arexxbifs 6y agoI honestly can't tell if this is a joke? 0.5 KLOC. Seven files. That's not over-engineered?
- deleted 6y ago[deleted]
- ohgodplsno 6y agoA lot of that is due some Android APIs being insane. Amongst all of those, the RecyclerView adapter will be over a hundred, because it is a stupidly verbose API. Layouts are XML, so, yeah, stupidly large too. Those two contribute to a lot of those lines. Not so much overengineered as lol-google-apis engineered. ViewModels are also due to the batshit insane android lifecycle, where you can easily be bitten in the ass. All of those are not for fun. They're because the Android APIs are terribly crap, or because you're not allowed to do certain things on the main thread (like, say, database queries) After that, you can very well put your activity/fragment/database logic in the same file, if you know you're never going to maintain it.
- Larrikin 6y agoNo matter how many times I write a recyclerview, which is usually atleast one for any new screen, it never stops being the worst part of Android dev for me.
- m_fayer 6y agoI used to say it a lot. It's been a long time now, but heck for old time's sake: how I miss Windows Phone.
- noema 6y ago"Best practice Android development" is soon to phase out XML (for the most part) with Jetpack Compose. Working with two way data binding in XML seemed like a good idea, until you had to debug it.
- ohgodplsno 6y ago"Soon". Compose is still in dev builds. Expect to see alpha in a few months, betas in two years and RCs/Release in three. Not exactly "soon".
- ShamelessC 6y agoI thought 12 was hyperbole for 3 or 4. All you've done is shown that the default encourages 7 files. Going from that to 12 with some questionably early refactoring sounds quite possible.
- ohgodplsno 6y agoThe quoted post says "dozens", plural. I can easily see new developers overengineering something that big.
- catalogia 6y ago> one list view which updated it's contents to filter results out of an SQLite database as you type into a text field In racket/gui this could be maybe 100 clean lines of code in one file.
- ohgodplsno 6y agoProbably, yes. Hower, does Racket handle configuration changes (orientation, language, etc.), recycling list items to lower memory usage, arbitrary layouts for lists (and not just a single line of text) with diffs calculated between renders, and more ? Android is complex, yes. Sometimes for no reason (hello God Activities). But sometimes, it has good reasons to do so. I actually wrote one, with the bare minimum. HNActivity.kt is 81 lines and handles updating the list, querying import android.database.sqlite.SQLiteDatabase import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.EditText import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.core.widget.addTextChangedListener import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import kotlin.concurrent.thread class ListItemVH(val view: TextView) : RecyclerView.ViewHolder(view) class HNActivity : AppCompatActivity() { private lateinit var recycler: RecyclerView private val adapter = object: RecyclerView.Adapter<ListItemVH>() { private var _items = listOf<String>() fun setItems(newItems: List<String>) { DiffUtil.calculateDiff(object: DiffUtil.Callback() { override fun getOldListSize(): Int = _items.size override fun getNewListSize(): Int = newItems.size override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) = _items[oldItemPosition] == newItems[newItemPosition] override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) = _items[oldItemPosition] == newItems[newItemPosition] }, true) _items = newItems } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListItemVH { val v = TextView(parent.context) return ListItemVH(v) } override fun getItemCount(): Int = _items.size override fun onBindViewHolder(holder: ListItemVH, position: Int) { holder.view.text = _items[position] } } private var search: String? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_scrolling) recycler = findViewById<RecyclerView>(R.id.fab) recycler.adapter = adapter recycler.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false) findViewById<EditText>(R.id.toolbar).addTextChangedListener { search = it?.toString()?.takeIf { str -> str != null } } } private fun performSearch() { thread { val db = SQLiteDatabase.openOrCreateDatabase("items.sqlite", null) val query = when (search) { null -> "SELECT text FROM table" else -> "SELECT text FROM table WHERE text = ?%" } val args = listOfNotNull(search).toTypedArray() val res = db.rawQuery(query, args) val text = mutableListOf<String>() while (!res.isAfterLast) { text += res.getString(0) } adapter.setItems(text) res.close() db.close() } } override fun onResume() { super.onResume() performSearch() } } Add in another 30 lines for the Activity layout, and you've got your thing. You've also got every single developer you'll work with hating you, and you'll hate maintaining this code. Just in those few lines, so much can go wrong (thread gets started and activity gets backgrounded? Oops, you crashed.)