RxJava网络无法实例化

时间:2018-11-20 07:13:47

标签: java android android-studio kotlin

我正在尝试运行以下链接在Kotlin中重写的应用程序: https://www.androidhive.info/RxJava/android-rxjava-networking-with-retrofit-gson-notes-app/

该示例最初是用Java编写的代码库。运行应用程序时出现以下错误。

2018-11-16 12:12:38.173 11843-11843/com.touchsides.rxjavanetworking E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.touchsides.rxjavanetworking, PID: 11843
    java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.touchsides.rxjavanetworking/com.touchsides.rxjavanetworking.view.MainActivity}: java.lang.InstantiationException: java.lang.Class<com.touchsides.rxjavanetworking.view.MainActivity> cannot be instantiated
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2843)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
     Caused by: java.lang.InstantiationException: java.lang.Class<com.touchsides.rxjavanetworking.view.MainActivity> cannot be instantiated
        at java.lang.Class.newInstance(Native Method)
        at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:69)
        at android.support.v4.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:43)
        at android.app.Instrumentation.newActivity(Instrumentation.java:1215)

MainActivity代码如下:

abstract class MainActivity : AppCompatActivity()
{

    lateinit var apiService: ApiService
    var disposable = CompositeDisposable()
    lateinit var mAdapter: NotesAdapter
    var noteList = ArrayList<Note>()

    companion object
    {
        val TAG = MainActivity::class.java.simpleName;

    }

    @BindView(R.id.coordinator_layout) var coordinatorLayout: CoordinatorLayout? = null

    @BindView(R.id.recycler_view) var recyclerView: RecyclerView? = null

    @BindView(R.id.txt_empty_notes_view) var noNotesView: TextView? = null

    override fun onCreate(savedInstanceState: Bundle?)
    {
        super.onCreate(savedInstanceState)

        getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        val toolbar = findViewById<Toolbar>(R.id.toolbar)
        toolbar.setTitle(getString(R.string.activity_title_home))
        setSupportActionBar(toolbar)

        fab.setOnClickListener { view ->

            showNoteDialog(false, null, -1);

        }
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean
    {
        // Inflate the menu; this adds items to the action bar if it is present.
        menuInflater.inflate(R.menu.menu_main, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean
    {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        return when (item.itemId)
        {
            R.id.action_settings -> true
            else -> super.onOptionsItemSelected(item)
        }
    }

    /**
     * Registering new user
     * sending unique id as device identification
     * https://developer.android.com/training/articles/user-data-ids.html
     */
    private fun registerUser()
    {
        // unique id to identify the device
        val uniqueId = UUID.randomUUID().toString()

        disposable.add(apiService.register(uniqueId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribeWith(
            object : DisposableSingleObserver<User>()
            {
                override fun onSuccess(user: User)
                {
                    // Storing user API Key in preferences
                    user.apiKey?.let { PrefUtils.storeApiKey(applicationContext, it) }

                    Toast.makeText(applicationContext,
                        "Device is registered successfully! ApiKey: " + PrefUtils.getApiKey(applicationContext),
                        Toast.LENGTH_LONG).show()
                }

                override fun onError(e: Throwable)
                {
                    Log.e(TAG, "onError: " + e.message)
                    showError(e)
                }
            }))
    }


    /**
     * Creating new note
     */
    private fun createNote(note: String)
    {
        disposable.add(apiService.createNote(note).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribeWith(
            object : DisposableSingleObserver<Note>()
            {

                override fun onSuccess(note: Note)
                {
                    if (!TextUtils.isEmpty(note.error))
                    {
                        Toast.makeText(applicationContext, note.error, Toast.LENGTH_LONG).show()
                        return
                    }

                    Log.d(TAG, "new note created: " + note.id + ", " + note.note + ", " + note.timestamp)

                    // Add new item and notify adapter
                    noteList.add(0, note)
                    mAdapter.notifyItemInserted(0)

                    toggleEmptyNotes()
                }

                override fun onError(e: Throwable)
                {
                    Log.e(TAG, "onError: " + e.message)
                    showError(e)
                }
            }))
    }

    /**
     * Updating a note
     */
    private fun updateNote(noteId: Int, note: String, position: Int)
    {
        disposable.add(apiService.updateNote(noteId,
            note).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribeWith(object :
            DisposableCompletableObserver()
        {
            override fun onComplete()
            {
                Log.d(TAG, "Note updated!")

                val n = noteList.get(position)
                n.note = (note)

                // Update item and notify adapter
                noteList.set(position, n)
                mAdapter.notifyItemChanged(position)
            }

            override fun onError(e: Throwable)
            {
                Log.e(TAG, "onError: " + e.message)
                showError(e)
            }
        }))
    }

    /**
     * Deleting a note
     */
    private fun deleteNote(noteId: Int, position: Int)
    {
        Log.e(TAG, "deleteNote: $noteId, $position")
        disposable.add(apiService.deleteNote(noteId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribeWith(
            object : DisposableCompletableObserver()
            {
                override fun onComplete()
                {
                    Log.d(TAG, "Note deleted! $noteId")

                    // Remove and notify adapter about item deletion
                    noteList.removeAt(position)
                    mAdapter.notifyItemRemoved(position)

                    Toast.makeText(this@MainActivity, "Note deleted!", Toast.LENGTH_SHORT).show()

                    toggleEmptyNotes()
                }

                override fun onError(e: Throwable)
                {
                    Log.e(TAG, "onError: " + e.message)
                    showError(e)
                }
            }))
    }

    /**
     * Shows alert dialog with EditText options to enter / edit
     * a note.
     * when shouldUpdate=true, it automatically displays old note and changes the
     * button text to UPDATE
     */
    private fun showNoteDialog(shouldUpdate: Boolean, note: Note?, position: Int)
    {
        val layoutInflaterAndroid = LayoutInflater.from(applicationContext)
        val view = layoutInflaterAndroid.inflate(R.layout.note_dialog, null)

        val alertDialogBuilderUserInput = AlertDialog.Builder(this@MainActivity)
        alertDialogBuilderUserInput.setView(view)

        val inputNote = view.findViewById<EditText>(R.id.note)
        val dialogTitle = view.findViewById<TextView>(R.id.dialog_title)
        dialogTitle.setText(if (!shouldUpdate) getString(R.string.lbl_new_note_title) else getString(R.string.lbl_edit_note_title))

        if (shouldUpdate && note != null)
        {
            inputNote.setText(note.note)
        }
        alertDialogBuilderUserInput.setCancelable(false).setPositiveButton(if (shouldUpdate) "update" else "save",
            DialogInterface.OnClickListener { dialogBox, id -> })
            .setNegativeButton("cancel", DialogInterface.OnClickListener { dialogBox, id -> dialogBox.cancel() })

        val alertDialog = alertDialogBuilderUserInput.create()
        alertDialog.show()

        alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(View.OnClickListener {
            // Show toast message when no text is entered
            if (TextUtils.isEmpty(inputNote.text.toString()))
            {
                Toast.makeText(this@MainActivity, "Enter note!", Toast.LENGTH_SHORT).show()
                return@OnClickListener
            } else
            {
                alertDialog.dismiss()
            }

            // check if user updating note
            if (shouldUpdate && note != null)
            {
                // update note by it's id
                updateNote(note.id, inputNote.text.toString(), position)
            } else
            {
                // create new note
                createNote(inputNote.text.toString())
            }
        })
    }

    /**
     * Opens dialog with Edit - Delete options
     * Edit - 0
     * Delete - 0
     */
    private fun showActionsDialog(position: Int)
    {
        val colors = arrayOf<CharSequence>("Edit", "Delete")

        val builder = AlertDialog.Builder(this)
        builder.setTitle("Choose option")
        builder.setItems(colors) { dialog, which ->
            if (which == 0)
            {
                showNoteDialog(true, noteList.get(position), position)
            } else
            {
                deleteNote(noteList.get(position).id, position)
            }
        }
        builder.show()
    }

    private fun toggleEmptyNotes()
    {
        if (noteList.size > 0)
        {
            noNotesView?.setVisibility(View.GONE)
        } else
        {
            noNotesView?.setVisibility(View.VISIBLE)
        }
    }


    /**
     * Showing a Snackbar with error message
     * The error body will be in json format
     * {"error": "Error message!"}
     */
    fun showError(e: Throwable)
    {
        var message = ""
        try
        {
            if (e is IOException)
            {
                message = "No internet connection!"
            }
            else (e is HttpException)
            {
                var error = e as HttpException
                var errorBody = error.response().errorBody().toString()
                val jObj = JSONObject(errorBody)
                message = jObj.getString("error")
            }

        }
        catch (e1: IOException)
        {
            e1.printStackTrace()
        }
        catch (e1: JSONException)
        {
            e1.printStackTrace()
        }
        catch (e1: Exception)
        {
            e1.printStackTrace()
        }

        if (TextUtils.isEmpty(message))
        {
            message = "Unknown error occurred! Check LogCat.";
        }

        val snackbar = coordinatorLayout?.let { Snackbar.make(it, message, Snackbar.LENGTH_LONG) }

        val sbView = snackbar?.getView()
        val textView = sbView?.findViewById<TextView>(android.support.design.R.id.snackbar_text)
        textView?.setTextColor(Color.YELLOW)
        snackbar?.show()
    }

    fun whiteNotificationBar(view: View)
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
        {
            var flags = view.getSystemUiVisibility();
            flags = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
            view.setSystemUiVisibility(flags);
            getWindow().setStatusBarColor(Color.WHITE);
        }
    }

    override fun onDestroy()
    {
        super.onDestroy()
        disposable.dispose()
    }
}

1 个答案:

答案 0 :(得分:0)

我发现了问题所在。似乎通过使用code complete选项,它最终使MainActivity类抽象了

abstract class MainActivity : AppCompatActivity()
{
 /// code base
}

代替

class MainActivity : AppCompatActivity()
{
 // code base
}