Adapter will nicht funktionieren

  • Antworten:5
Robbiani Renato
  • Forum-Beiträge: 609

17.08.2021, 22:02:27 via Website

Hallo zusammen

Ich habe ein Beispiel aus einem Buch. Dies will aber einfach nicht laufen. Ich habe den Code bereits Zeile um Zeile verglichen. Ich habe kein unterschied gefunden.

Das Problem ist folgendes. Die Zeile "updateAdapter()" ist rot unterstrichen mit der Fehlermeldung, Type missmatch. Erwartet wird Boolean aber gefunden wird Unit. Das kann ich noch verstehen.

private val contentObserver = object : ContentObserver(handler){
    override fun onChange(selfChange: Boolean) {
        updateAdapter()
    }
}

Denn in der onChange Methode wird ein Boolean gefordert. Wenn ich aber nun die Methode auf Unit wechsle, dann wird sie rot unterstrichen mit der Begründung dass sie nicht mehr überschrieben wird.

Warum geht der Adapter nicht?
Vielleicht findet jemand das Problem. Wenn nicht ist auch ok.

package ch.robbisoft.calllogdemo

import android.Manifest
import android.content.ContentValues
import android.content.pm.PackageManager
import android.database.ContentObserver
import android.database.Cursor
import androidx.appcompat.app.AppCompatActivity
import android.os.*
import android.provider.CallLog
import android.view.View
import android.widget.*
import android.widget.AdapterView.OnItemClickListener
import android.widget.ListView
import android.widget.TextView
import ch.robbisoft.calllogdemo.databinding.ActivityMainBinding
import kotlin.concurrent.thread
import androidx.cursoradapter.widget.SimpleCursorAdapter
import kotlin.jvm.Throws

private const val REQUEST_READ_CALL_LOG = 123
private const val REQUEST_WRITE_CALL_LOG = 321

class MainActivity : AppCompatActivity() {

private lateinit var binding : ActivityMainBinding
private lateinit var listview : ListView

private val handler = Handler(Looper.getMainLooper())
private val contentObserver = object : ContentObserver(handler){
    override fun onChange(selfChange: Boolean) {
        updateAdapter()
    }
}
private var contentObserverWasRegistered = false
private lateinit var cursorAdapter: SimpleCursorAdapter

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val view = binding.root
    setContentView(view)

    listview = binding.tvAusgabe

    cursorAdapter = SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, null, arrayOf(CallLog.Calls.NUMBER), intArrayOf(android.R.id.text1), 0)
    cursorAdapter.viewBinder = SimpleCursorAdapter.ViewBinder{
        view : View, cursor : Cursor, columnIndex : Int ->
        if (columnIndex == cursor.getColumnIndex(CallLog.Calls.NUMBER)){
            var number = cursor.getString(columnIndex)
            var isNew = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.NEW))
            if (isNew != 0){
                number += " (neu)"
            }
            (view as TextView).text = number
            true
        }else {
            false
        }
        listview.adapter = cursorAdapter
        listview.onItemClickListener = OnItemClickListener { _ : AdapterView<*>?, view2 : View, position : Int, id : Long ->
            val c = cursorAdapter.getItem(position) as Cursor
            val callLogId = c.getLong(c.getColumnIndex(CallLog.Calls._ID))
            updateCallLogData(callLogId)
        }
        updateAdapter()
    }
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (grantResults.isNotEmpty() && grantResults[0] ==
        PackageManager.PERMISSION_GRANTED) {
        when (requestCode) {
            REQUEST_READ_CALL_LOG -> updateAdapter()
            REQUEST_WRITE_CALL_LOG -> {
            }
        }
    }
}

private fun updateAdapter(){
    if(checkSelfPermission(Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED){
        requestPermissions(arrayOf(Manifest.permission.READ_CALL_LOG), REQUEST_READ_CALL_LOG)
    }else{
        if(!contentObserverWasRegistered){
            contentResolver.registerContentObserver(CallLog.Calls.CONTENT_URI, false, contentObserver)
            contentObserverWasRegistered = true
        }
        thread {
            val c = getMissedCalls()
            runOnUiThread {cursorAdapter.changeCursor(c)}
        }
    }
    if(checkSelfPermission(Manifest.permission.WRITE_CALL_LOG) != PackageManager.PERMISSION_GRANTED){
        requestPermissions(arrayOf(Manifest.permission.WRITE_CALL_LOG), REQUEST_WRITE_CALL_LOG)
    }
}

private fun updateCallLogData(id : Long){
    if(checkSelfPermission(Manifest.permission.WRITE_CALL_LOG) == PackageManager.PERMISSION_GRANTED) {
        val values = ContentValues()
        values.put(CallLog.Calls.NEW, 0)
        val where = CallLog.Calls._ID + "= ?"
        val selectionArgs = arrayOf(id.toString())
        contentResolver.update(CallLog.Calls.CONTENT_URI, values, where, selectionArgs)
    }
}

override fun onDestroy() {
    super.onDestroy()
    if(contentObserverWasRegistered){
        contentResolver.unregisterContentObserver(contentObserver)
    }
}

@Throws(SecurityException::class)
private fun getMissedCalls() : Cursor?{
    val projection = arrayOf(CallLog.Calls.NUMBER, CallLog.Calls.DATE, CallLog.Calls.NEW, CallLog.Calls._ID)
    val selection = CallLog.Calls.TYPE + " = ?"
    val selectionArgs = arrayOf(CallLog.Calls.MISSED_TYPE.toString())
    return contentResolver.query(CallLog.Calls.CONTENT_URI, projection, selection, selectionArgs, null)
}

}

Gruss Renato

Kommentieren
Jokel
  • Forum-Beiträge: 1.530

18.08.2021, 08:49:36 via Website

Hallo

Wenn du eine Methode überschreiben willst dann muss die genau so aussehen wie die in der Klasse definiert ist.
Gleiche Parameter.....

Sonst erstellt du eine neue Methode, und überschreibst nicht ,dann ist das override logischer weise falsch.

Beim override etwas an dem Aufruf ( zb Parameterübergabe) zu ändern ist immer der falsche Weg.

— geändert am 18.08.2021, 09:31:10

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

18.08.2021, 09:44:15 via Website

Das Problem dürfte sein das die Methode „updateAdapter()“ private ist.

Du hast in der Zeile ein Objekt Instanz von einer anonymen Klasse erstellt.
Du bist also in ein der override Methode in einer anderen Klasse, durch das privat kannst du nicht auf die Methode zugreifen .

Hilfreich?
Pascal P.
Kommentieren
Robbiani Renato
  • Forum-Beiträge: 609

20.08.2021, 20:28:25 via Website

Ciao Jokel

Leider ist das nicht die Lösung vom Problem.

Gruss Renato

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

20.08.2021, 20:52:18 via Website

Was hast du denn jetzt geändert?

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

20.08.2021, 20:59:07 via Website

Laut Doku ist die Methode onChange überladen. Hast du auch die richtige overeidet?

Hilfreich?
Kommentieren