Этот магазин заметок в моем телефоне запускается при первом запуске, затем я нажимаю кнопку добавления, и приложение вылетает. Проблема с загрузкой данных в приложение с телефона - PullRequest
0 голосов
/ 01 мая 2020

Это приложение будет выполнять две вещи: одну, показывать все заметки, сохраненные пользователем на устройстве, и добавлять заметки на устройстве. Но когда я запускаю приложение в первый раз, предполагая, что данные не сохранены, а база данных, в которой предполагается хранить данные, пуста, приложение запускается, но когда я нажимаю кнопку добавления заметок, оно вылетает, а затем, если я очищаю приложение из последних и открыть снова, он падает в основном потому, что в базе данных есть некоторые данные. И если я очищаю хранилище и затем запускаю, он запускается так, когда я пытаюсь сохранить какие-либо данные, а затем запускаю, происходит сбой. В моем коде я перезагружаю recyclerView после ввода новых заметок и первого открытия приложения, вызывая метод reload в классе адаптера, и, скорее всего, у этого метода есть некоторая проблема в классе адаптера.

MainActivity. java

package com.example.notes;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.room.Room;
import androidx.room.RoomDatabase;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;

import com.google.android.material.floatingactionbutton.FloatingActionButton;

public class MainActivity extends AppCompatActivity {
    private RecyclerView recyclerView;
    private NotesAdapter adapter;
    private RecyclerView.LayoutManager layoutManager;
    public static NoteDatabase database;

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

    database = Room.databaseBuilder(getApplicationContext(), NoteDatabase.class, "notes")
                .allowMainThreadQueries()
                .build();

    recyclerView = findViewById(R.id.recycler_view);
    layoutManager = new LinearLayoutManager(this);
    adapter = new NotesAdapter();

    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setAdapter(adapter);

    FloatingActionButton button = findViewById(R.id.add_note_button);

    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            database.noteDao().create();
            //Log.e("cs50", "Error has occured");
            adapter.reload();
            //Log.e("cs50", "Error has occured");
        }
    });


    adapter.reload();
}
}

Примечание. java

package com.example.notes;

import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;

@Entity(tableName = "notes")
public class Note
{
    @PrimaryKey
    public int id;
    @ColumnInfo(name = "contents")
    public String contents;

}

NoteDao. java Интерфейс

package com.example.notes;

import androidx.room.Dao;
import androidx.room.Query;

import java.util.List;

@Dao
public interface NoteDao
{
    @Query("INSERT INTO notes (contents) VALUES ('New note')")
    void create();

    @Query("SELECT * FROM notes")
    List<Note> getAllNotes();

    @Query("UPDATE notes SET contents = :contents WHERE id = :id")
    void save(String contents, int id);
}

NoteDataBase. java

package com.example.notes;

import androidx.room.Database;
import androidx.room.RoomDatabase;

@Database(entities = {Note.class}, version = 1)
public abstract class NoteDatabase extends RoomDatabase
{
    public abstract NoteDao noteDao();
}

NotesAdapter. java

    package com.example.notes;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;

public class NotesAdapter extends RecyclerView.Adapter<NotesAdapter.NoteViewHolder>
{
    public static class NoteViewHolder extends RecyclerView.ViewHolder
    {
        LinearLayout containerView;
        TextView textView;
        NoteViewHolder(View view)
        {
            super(view);
            containerView = view.findViewById(R.id.note_row);
            textView = view.findViewById(R.id.note_row_text);
        }
    }

    public List<Note> notes = new ArrayList<>();

    @NonNull
    @Override
    public NoteViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.note_row, parent, false);

        return new NoteViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull NoteViewHolder holder, int position) {
        Note current = notes.get(position);
        holder.textView.setText(current.contents);
    }

    @Override
    public int getItemCount() {
        return notes.size();
    }

    public void reload()
    {
        notes = MainActivity.database.noteDao().getAllNotes();
        notifyDataSetChanged();
    }

}

activity_main. xml

    <?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/recycler_view"/>

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/add_note_button"
        android:layout_gravity="bottom|right"
        android:layout_margin="16dp"
        app:srcCompat = "@android:drawable/ic_input_add"
        android:tint="@color/cardview_light_background"
        />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

note_row. xml

    <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/note_row">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/note_row_text"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

build.gradle

    apply plugin: 'com.android.application'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.3"

    defaultConfig {
        applicationId "com.example.notes"
        minSdkVersion 21
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.recyclerview:recyclerview:1.0.0'
    implementation 'com.google.android.material:material:1.0.0'
    implementation "androidx.room:room-runtime:2.2.5"
    annotationProcessor "androidx.room:room-compiler:2.2.5"

    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

Сообщение об ошибке в журнале

1 Ответ

0 голосов
/ 01 мая 2020

Привет, я вижу две проблемы в вашем коде

1) Вам нужно создать экземпляр вашей базы данных, вы не можете просто так назвать свой DAO

public static synchronized MyDB getInstance(Context context) {
    if (instance == null) {
        instance = Room.databaseBuilder(context.getApplicationContext(), MyDB.class, DB_NAME)
               .fallbackToDestructiveMigration()
               .addCallback(roomCallback)
               .build();
     }
      return instance;
}

2) Когда манипулируя Room, вы должны использовать другой поток для любого взаимодействия с базой данных, поэтому вам нужно вызвать функцию Asyn c

Пример функции вставки Asynchronous ->

private static class InsertProductAsyncTask extends AsyncTask<Product, Void, Void> {
        private ProductDao  productDao;

        private InsertProductAsyncTask(ProductDao productDao) { this.productDao = productDao; }

        @Override
        protected Void doInBackground(Product... product) {
            productDao.insertProduct(product[0]);
            return null;
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...