1

Whenever I want to start my "NotenActivity", it Shows me this error:

  Caused by: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
        at androidx.room.RoomDatabase.assertNotMainThread(RoomDatabase.java:209)
        at androidx.room.RoomDatabase.query(RoomDatabase.java:237)
        at com.example.mykolproject.persistance.dao.NoteDao_Impl.getnAll(NoteDao_Impl.java:121)
        at com.example.mykolproject.NoteRepository.<init>(NoteRepository.java:23)
        at com.example.mykolproject.NoteViewModel.<init>(NoteViewModel.java:20)
        at java.lang.reflect.Constructor.newInstance0(Native Method) 
        at java.lang.reflect.Constructor.newInstance(Constructor.java:343) 
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:200) 
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:135) 
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:103) 
        at com.example.mykolproject.NotenActivity.onCreate(NotenActivity.java:130) 
        at android.app.Activity.performCreate(Activity.java:7458) 
        at android.app.Activity.performCreate(Activity.java:7448) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1286) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3409) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3614) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:86) 
        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:2199) 
        at android.os.Handler.dispatchMessage(Handler.java:112) 
        at android.os.Looper.loop(Looper.java:216) 
        at android.app.ActivityThread.main(ActivityThread.java:7625) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987) 

Here are my affected Activitys:

package com.example.mykolproject.persistance.dao;

import android.database.Cursor;
import androidx.room.EntityDeletionOrUpdateAdapter;
import androidx.room.EntityInsertionAdapter;
import androidx.room.RoomDatabase;
import androidx.room.RoomSQLiteQuery;
import androidx.sqlite.db.SupportSQLiteStatement;
import com.example.mykolproject.persistance.entities.Note;
import java.lang.Override;
import java.lang.String;
import java.lang.SuppressWarnings;
import java.util.ArrayList;
import java.util.List;

@SuppressWarnings("unchecked")
public final class NoteDao_Impl implements NoteDao {
  private final RoomDatabase __db;

  private final EntityInsertionAdapter __insertionAdapterOfNote;

  private final EntityDeletionOrUpdateAdapter __deletionAdapterOfNote;

  private final EntityDeletionOrUpdateAdapter __updateAdapterOfNote;

  public NoteDao_Impl(RoomDatabase __db) {
    this.__db = __db;
    this.__insertionAdapterOfNote = new EntityInsertionAdapter<Note>(__db) {
      @Override
      public String createQuery() {
        return "INSERT OR ABORT INTO `note_table`(`id`,`titlefach`,`noten`) VALUES (nullif(?, 0),?,?)";
      }

      @Override
      public void bind(SupportSQLiteStatement stmt, Note value) {
        stmt.bindLong(1, value.getId());
        if (value.titlefach == null) {
          stmt.bindNull(2);
        } else {
          stmt.bindString(2, value.titlefach);
        }
        if (value.getNoten() == null) {
          stmt.bindNull(3);
        } else {
          stmt.bindString(3, value.getNoten());
        }
      }
    };
    this.__deletionAdapterOfNote = new EntityDeletionOrUpdateAdapter<Note>(__db) {
      @Override
      public String createQuery() {
        return "DELETE FROM `note_table` WHERE `id` = ?";
      }

      @Override
      public void bind(SupportSQLiteStatement stmt, Note value) {
        stmt.bindLong(1, value.getId());
      }
    };
    this.__updateAdapterOfNote = new EntityDeletionOrUpdateAdapter<Note>(__db) {
      @Override
      public String createQuery() {
        return "UPDATE OR ABORT `note_table` SET `id` = ?,`titlefach` = ?,`noten` = ? WHERE `id` = ?";
      }

      @Override
      public void bind(SupportSQLiteStatement stmt, Note value) {
        stmt.bindLong(1, value.getId());
        if (value.titlefach == null) {
          stmt.bindNull(2);
        } else {
          stmt.bindString(2, value.titlefach);
        }
        if (value.getNoten() == null) {
          stmt.bindNull(3);
        } else {
          stmt.bindString(3, value.getNoten());
        }
        stmt.bindLong(4, value.getId());
      }
    };
  }

  @Override
  public void insert(Note note) {
    __db.beginTransaction();
    try {
      __insertionAdapterOfNote.insert(note);
      __db.setTransactionSuccessful();
    } finally {
      __db.endTransaction();
    }
  }

  @Override
  public void delete(Note note) {
    __db.beginTransaction();
    try {
      __deletionAdapterOfNote.handle(note);
      __db.setTransactionSuccessful();
    } finally {
      __db.endTransaction();
    }
  }

  @Override
  public void update(Note note) {
    __db.beginTransaction();
    try {
      __updateAdapterOfNote.handle(note);
      __db.setTransactionSuccessful();
    } finally {
      __db.endTransaction();
    }
  }

  @Override
  public List<Note> getnAll() {
    final String _sql = "SELECT * FROM note_table";
    final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
    final Cursor _cursor = __db.query(_statement);
    try {
      final int _cursorIndexOfId = _cursor.getColumnIndexOrThrow("id");
      final int _cursorIndexOfTitlefach = _cursor.getColumnIndexOrThrow("titlefach");
      final int _cursorIndexOfNoten = _cursor.getColumnIndexOrThrow("noten");
      final List<Note> _result = new ArrayList<Note>(_cursor.getCount());
      while(_cursor.moveToNext()) {
        final Note _item;
        final String _tmpTitlefach;
        _tmpTitlefach = _cursor.getString(_cursorIndexOfTitlefach);
        final String _tmpNoten;
        _tmpNoten = _cursor.getString(_cursorIndexOfNoten);
        _item = new Note(_tmpTitlefach,_tmpNoten);
        final int _tmpId;
        _tmpId = _cursor.getInt(_cursorIndexOfId);
        _item.setId(_tmpId);
        _result.add(_item);
      }
      return _result;
    } finally {
      _cursor.close();
      _statement.release();
    }
  }
}

package com.example.mykolproject;


import android.app.Application;
import android.os.AsyncTask;

import androidx.lifecycle.LiveData;

import com.example.mykolproject.persistance.dao.NoteDao;
import com.example.mykolproject.persistance.entities.AppDatabase;
import com.example.mykolproject.persistance.entities.Note;

import java.util.List;


public class NoteRepository {
    private NoteDao notenDao;
    private LiveData<List<Note>> allNoten;

    public NoteRepository(Application application) {
        AppDatabase database = AppDatabase.getInstance(application);
        notenDao = database.NoteDao();
        allNoten = (LiveData<List<Note>>) notenDao.getnAll();
    }

    public void insert(LiveData<List<Note>> note) {
        new InsertNoteAsyncTask(notenDao).execute((Runnable) note);
    }

    public void update(LiveData<List<Note>> note) {
        new UpdateNoteAsyncTask(notenDao).execute((Runnable) note);
    }

    public void delete(LiveData<List<Note>> note) {
        new DeleteNoteAsyncTask(notenDao).execute((Runnable) note);
    }


    public LiveData<List<Note>> getAllNoten() {
        return getAllNoten();
    }

    private static class InsertNoteAsyncTask extends AsyncTask<Note, Void, Void> {
        private NoteDao noteDao;

        private InsertNoteAsyncTask(NoteDao noteDao) {
            this.noteDao = noteDao;
        }

        @Override
        protected Void doInBackground(Note... noten) {
            noteDao.insert(noten[0]);
            return null;
        }
    }

    private static class UpdateNoteAsyncTask extends AsyncTask<Note, Void, Void> {
        private NoteDao noteDao;

        private UpdateNoteAsyncTask(NoteDao noteDao) {
            this.noteDao = noteDao;
        }

        @Override
        protected Void doInBackground(Note... noten) {
            noteDao.update(noten[0]);
            return null;
        }
    }

    private static class DeleteNoteAsyncTask extends AsyncTask<Note, Void, Void> {
        private NoteDao noteDao;

        private DeleteNoteAsyncTask(NoteDao noteDao) {
            this.noteDao = noteDao;
        }

        @Override
        protected Void doInBackground(Note... noten) {
            noteDao.delete(noten[0]);
            return null;
        }
    }


}

package com.example.mykolproject;

import android.app.Application;

import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;

import com.example.mykolproject.persistance.entities.Note;

import java.util.List;


public class NoteViewModel extends AndroidViewModel {
    private NoteRepository repository;
    private LiveData<List<Note>> allNoten;

    public NoteViewModel(@NonNull Application application) {
        super(application);
        repository = new NoteRepository(application);
        allNoten = repository.getAllNoten();
    }

    public void insert(Note note) {
        repository.insert(allNoten);
    }

    public void update(Note note) {
        repository.update(allNoten);
    }

    public void delete(Note note) {
        repository.delete(allNoten);
    }

    public LiveData<List<Note>> getAllNotes() {
        return allNoten;
    }
}

package com.example.mykolproject;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;


import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.example.mykolproject.persistance.entities.Note;

import java.util.List;


public class NotenActivity extends AppCompatActivity  {
    public String TAG = "NotenActivity";

    public static final String NOTEN_MESSAGE = "com.example.MyOLProject.NOTEN";

    private RecyclerView recyclerView;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.LayoutManager layoutManager;

    public static final int ADD_NOTE_REQUEST = 1;
    public static final int EDIT_NOTE_REQUEST = 2;

    private NoteViewModel noteViewModel;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_noten);

        //  final EditText editFach = findViewById(R.id.edit_fach);


        recyclerView = (RecyclerView) findViewById(R.id.notenList);

        recyclerView.setHasFixedSize(true);

        layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);

        Button btnAddNoten = findViewById(R.id.btn_addNote);

        btnAddNoten.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i(TAG, "onClick: AddNoten");
                startAddNoten();
            }
        });



        ImageButton btnFach = findViewById(R.id.ibFach);
        btnFach.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                Log.i(TAG,"onClick: Fach");
                startFach();

            }

        });

        ImageButton btnHome = findViewById(R.id.ibHome);
        btnHome.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                Log.i(TAG,"onClick: Home");
                startHome();

            }

        });

        ImageButton btnHausaufgaben = findViewById(R.id.ibHausaufgaben);
        btnHausaufgaben.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                Log.i(TAG,"onClick: Hausaufgaben");
                startHausaufgaben();

            }

        });

        ImageButton btnKalender = findViewById(R.id.ibInfo);
        btnKalender.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                Log.i(TAG,"onClick: Kalender");
                startKalender();

            }

        });

        Button buttonAddNote = findViewById(R.id.btn_addNote);
        buttonAddNote.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(NotenActivity.this, AddEditNoteActivity.class);
                startActivityForResult(intent, ADD_NOTE_REQUEST);
            }
        });

        RecyclerView recyclerView = findViewById(R.id.notenList);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setHasFixedSize(true);

        final NotenListAdapter adapter = new NotenListAdapter();
        recyclerView.setAdapter(adapter);

        noteViewModel = ViewModelProviders.of(this).get(NoteViewModel.class);
        noteViewModel.getAllNotes().observe(this, new Observer<List<Note>>() {
            @Override
            public void onChanged(@Nullable List<Note> noten) {
                adapter.setNotes(noten);
            }
        });

        new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0,
                ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
            @Override
            public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
                return false;
            }

            @Override
            public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
                noteViewModel.delete(adapter.getNoteAt(viewHolder.getAdapterPosition()));
                Toast.makeText(NotenActivity.this, "Note deleted", Toast.LENGTH_SHORT).show();
            }
        }).attachToRecyclerView(recyclerView);

        adapter.setOnItemClickListener(new NotenListAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(Note note) {
                Intent intent = new Intent(NotenActivity.this, AddEditNoteActivity.class);
                intent.putExtra(AddEditNoteActivity.EXTRA_ID, note.getId());
                intent.putExtra(AddEditNoteActivity.EXTRA_TITLE, note.getTitleFach());
                intent.putExtra(AddEditNoteActivity.EXTRA_DESCRIPTION, note.getNoten());
                startActivityForResult(intent, EDIT_NOTE_REQUEST);
            }
        });



    }


    private void startAddNoten(){
        Intent addNotenIntent = new Intent(this,AddNotenActivity.class);
        startActivity(addNotenIntent);
    }

    private void startFach(){
        Intent fachIntent = new Intent(this,FachActivity.class);
        startActivity(fachIntent);
    }
    private void startHome(){
        Intent homeIntent = new Intent(this,MainActivity.class);
        startActivity(homeIntent);
    }
    private void startHausaufgaben(){
        Intent hausaufgabenIntent = new Intent(this,HausaufgabenActivity.class);
        startActivity(hausaufgabenIntent);
    }
    private void startKalender(){
        Intent kalenderIntent = new Intent(this,InfoActivity.class);
        startActivity(kalenderIntent);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == ADD_NOTE_REQUEST && resultCode == RESULT_OK) {
            String title = data.getStringExtra(AddEditNoteActivity.EXTRA_TITLE);
            String description = data.getStringExtra(AddEditNoteActivity.EXTRA_DESCRIPTION);

            Note note = new Note(title, description);
            noteViewModel.insert(note);

            Toast.makeText(this, "Note saved", Toast.LENGTH_SHORT).show();
        } else if (requestCode == EDIT_NOTE_REQUEST && resultCode == RESULT_OK) {
            int id = data.getIntExtra(AddEditNoteActivity.EXTRA_ID, -1);

            if (id == -1) {
                Toast.makeText(this, "Note can't be updated", Toast.LENGTH_SHORT).show();
                return;
            }

            String title = data.getStringExtra(AddEditNoteActivity.EXTRA_TITLE);
            String description = data.getStringExtra(AddEditNoteActivity.EXTRA_DESCRIPTION);

            Note note = new Note(title, description);
            note.setId(id);
            noteViewModel.update(note);

            Toast.makeText(this, "Note updated", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, "Note not saved", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater menuInflater = getMenuInflater();
        menuInflater.inflate(R.menu.main_menu, menu);
        return true;
    }

   /* @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.delete_all_notes:
                noteViewModel.deleteAllNotes();
                Toast.makeText(this, "All notes deleted", Toast.LENGTH_SHORT).show();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
}*/


}

If you Need any other activities just let me know. My "NotenActivity" is like my MainActivity. Thank you very much !

G. Blake Meike
  • 6,615
  • 3
  • 24
  • 40
Laurence
  • 11
  • 4
  • As far as I understand you are calling the `getAllNoten()` method from within your main thread that is also used for UI. So you should move this call to the io thread to make it run asynchronously during ui can proceed. See: https://developer.android.com/training/articles/perf-anr.html – antoshkaa Jan 31 '20 at 14:53

2 Answers2

0

Try using some RxJava, that can probably help you out. But since you're using Room, LiveData, and ViewModel you can probably try using this AppExecutor class. This usually helps me out when I'm doing Database and Network operations.

Also be careful when running on the UI/Main Thread, for Database operations with lots of data its always best practice to do it on a separate thread.

import android.os.Looper;
import android.support.annotation.NonNull;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class AppExecutors {
    private static final Object LOCK = new Object();
    private static AppExecutors sInstance;
    private final Executor diskIO;
    private final Executor mainThread;
    private final Executor networkIO;

    private AppExecutors(Executor diskIO, Executor networkIO, Executor mainThread) {
        this.diskIO = diskIO;
        this.networkIO = networkIO;
        this.mainThread = mainThread;
    }

    public static AppExecutors getInstance() {
        if (sInstance == null) {
            synchronized (LOCK) {
                sInstance = new AppExecutors(Executors.newSingleThreadExecutor(),
                        Executors.newFixedThreadPool(3),
                        new MainThreadExecutor());
            }
        }
        return sInstance;
    }

    public Executor diskIO() {
        return diskIO;
    }

    public Executor mainThread() {
        return mainThread;
    }

    public Executor networkIO() {
        return networkIO;
    }

    private static class MainThreadExecutor implements Executor {
        private Handler mainThreadHandler = new Handler(Looper.getMainLooper());

        @Override
        public void execute(@NonNull Runnable command) {
            mainThreadHandler.post(command);
        }
    }
}

//Then you can do something like this. 
```AppExecutors.getInstance().getDiskIO.execute(()->database.NoteDao().getnAll());```
OdinsBeard
  • 27
  • 4
0

Maybe you could look on widely accepted solution of this problem, it could bring you to solution of your problem too...