I am making an launcher for my phone and I need to sort the apps by alphabet.
Appslist = ArrayList<AppInfo>()
val i = Intent(Intent.ACTION_MAIN, null)
i.addCategory(Intent.CATEGORY_LAUNCHER)
val allApps = this.packageManager.queryIntentActivities(i, 0)
for (ri in allApps) {
val app = AppInfo()
app.label = ri.loadLabel(this.packageManager)
app.packageName = ri.activityInfo.packageName
app.icon = ri.activityInfo.loadIcon(this.packageManager)
if(app.label?.toString()!!.length >= searchWord.length && app.label?.toString()!!.substring(0, searchWord.length) == searchWord.toUpperCase() && searchWord != "" ||
app.label?.toString()!!.length >= searchWord.length && app.label?.toString()!!.substring(0, searchWord.length) == searchWord.toLowerCase() && searchWord != "" ||
app.label?.toString()!!.length >= searchWord.length && app.label?.toString()!!.substring(0, searchWord.length) == searchWord.capitalize() && searchWord != "" ||
app.label?.toString()!!.length >= searchWord.length && app.label?.toString()!!.substring(0, searchWord.length) == searchWord && searchWord != ""){
if(app.packageName != "com.david.launcher" ){
Appslist.add(app)
}
}
if(searchWord == ""){
if(app.packageName != "com.david.launcher"){
Appslist.add(app)
}
}
}
Here is my list type (I don't really know if it's called list type, but I hope you'll understand):
public class AppInfo {
internal var label: CharSequence? = null
internal var packageName: CharSequence? = null
internal var icon: Drawable? = null
internal var isInFav: Boolean? = false
To sort an Array of Integers in Kotlin, use Array. sort() method. sort() method sorts the calling array in-place in ascending order. To sort Integer Array in descending order, call sortDescending() method on this Array.
To sort the ArrayList, you need to simply call the Collections. sort() method passing the ArrayList object populated with country names. This method will sort the elements (country names) of the ArrayList using natural ordering (alphabetically in ascending order).
The idiomatic way is to use the sortedBy
extension method for List
if you want to sort into a copy of the list. Or use sortBy
extension on a MutableList
if you want to sort in-place without a copy. An ArrayList
would work as either list type.
// Sort a readonly list into a copy of the list
val appsList: List<AppInfo> = ...
val sortedAppsList = appsList.sortedBy { it.label?.toString() }
versus:
// Sort a mutable list in-place
val appsList: MutableList<AppInfo> = ...
appList.sortBy { it.label?.toString() }
and if holding as an ArrayList
it is the same, but not idiomatic to have a reference directly to this concrete type.
// Sort an ArrayList list into a copy of the list
val appsList: ArrayList<AppInfo> = ... // ALERT! not idiomatic
val sortedAppsList = appsList.sortedBy { it.label?.toString() }
// or if you want, feel free to sort in-place
appsList.sortBy { it.label?.toString() }
Note the toString()
on the label: CharSequence
member. You have to be careful sorting on a reference of type CharSequence
as it is undefined what is its behavior for sorting (see: https://docs.oracle.com/javase/7/docs/api/java/lang/CharSequence.html)
This interface does not refine the general contracts of the equals and hashCode methods. The result of comparing two objects that implement CharSequence is therefore, in general, undefined.
If the CharSequence
is already a String
(likely is), then there is no harm in calling toString()
as it just returns itself.
Also keep in mind that the nullable CharSequence
has to be handled as well, and you need to decide where you want nulls: at the start or end of the list. I think the default is for them to go to the start.
Other notes about your code in the question:
Use the List
or MutableList
interface instead of the concrete class to reference the type, and use the methods from Kotlin stdlib to do actions upon the list. Also use val
instead of var
for references that will not change (meaning it will always point to the same list regardless of whether the list contents could change).
The big if
statement you have can be reduced a lot, go from...
if(app.label?.toString()!!.length >= searchWord.length && app.label?.toString()!!.substring(0, searchWord.length) == searchWord.toUpperCase() && searchWord != "" ||
app.label?.toString()!!.length >= searchWord.length && app.label?.toString()!!.substring(0, searchWord.length) == searchWord.toLowerCase() && searchWord != "" ||
app.label?.toString()!!.length >= searchWord.length && app.label?.toString()!!.substring(0, searchWord.length) == searchWord.capitalize() && searchWord != "" ||
app.label?.toString()!!.length >= searchWord.length && app.label?.toString()!!.substring(0, searchWord.length) == searchWord && searchWord != ""){
if(app.packageName != "com.david.launcher" ){
Appslist.add(app)
}
}
if(searchWord == ""){
if(app.packageName != "com.david.launcher"){
Appslist.add(app)
}
}
to simpler:
if (app.packageName != "com.david.launcher" &&
(searchWord.isBlank() ||
app.label?.startsWith(searchWord, ignoreCase = true) == true)) {
appsList.add(app)
}
You should browse the standard library to get an idea of what is available so that you broaden your toolkit for the future.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With