пытается обновить элемент в firebase из приложения, но он просто добавляет другой элемент - PullRequest
0 голосов
/ 27 апреля 2020

Я пытаюсь обновить элемент в моем приложении, но когда я отправляю его на обновления, он просто добавляет другой элемент. Я новичок в android, поэтому не знаю, почему это происходит. Я храню автомобильные предметы в обзоре переработчика. это представление переработчика, которое я использую:

adapter = new FirebaseRecyclerAdapter<Event, eventAdapter>(options) {
    @Override
    protected void onBindViewHolder(@NonNull eventAdapter holder, int position, @NonNull final Event model) {
        holder.make.setText(model.getCarMake());
        holder.type.setText(model.getCarType());
        holder.year.setText(model.getCarYear());

        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getActivity(), updateDeleteCars.class);
                intent.putExtra("make", model.getCarMake());
                intent.putExtra("type", model.getCarType());
                intent.putExtra("year", model.getCarYear());
                startActivity(intent);
            }
        });

    }

Каждый элемент можно щелкнуть, а затем вы попадете на страницу обновления. это та страница

public class updateDeleteCars extends AppCompatActivity {

    Button update;
    Button delete;
    EditText make;
    EditText type;
    EditText year;
    TextView cancel;
    DatabaseReference databaseReference;
    FirebaseUser user;
    String userId;
    private String key;

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

        update = (Button) findViewById(R.id.updateCar);
        delete = (Button) findViewById(R.id.deleteCar);
        cancel = (TextView) findViewById(R.id.cancelCar);
        make = (EditText) findViewById(R.id.updateMake);
        type = (EditText) findViewById(R.id.updateType);
        year = (EditText) findViewById(R.id.updateYear);

        make.setText(getIntent().getStringExtra("make"));
        type.setText(getIntent().getStringExtra("type"));
        year.setText(getIntent().getStringExtra("year"));
        user = FirebaseAuth.getInstance().getCurrentUser();
        userId = user.getUid();

        databaseReference = FirebaseDatabase.getInstance().getReference("Cars").child(userId);
        key = databaseReference.getKey();

        cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(getApplicationContext(),MainActivity.class));
            }
        });

        update.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                databaseReference.child(key).child("carMake").setValue(make.getText().toString());
                databaseReference.child(key).child("carType").setValue(type.getText().toString());
                databaseReference.child(key).child("carYear").setValue(year.getText().toString());

            }
        });

        delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                databaseReference.child(key).removeValue();

            }
        });
    }
}

Я думаю, это потому, что существует фактическая связь между элементом, который я нажимаю, и элементом, который я загружаю. Моя структура базы данных имеет вложенные ключи, поэтому я думаю, что моя проблема в том, что я не получаю доступ к вложенному ключу. это структура базы данных:

database Structure

Второй случай произошел, когда я попытался обновить первый элемент. Есть предложения?

Редактировать: Stacktrace

Process: com.example.carcrashdetection, PID: 9023
    com.google.firebase.database.DatabaseException: Can't convert object of type java.lang.String to type com.example.carcrashdetection.Event
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertBean(com.google.firebase:firebase-database@@19.2.1:435)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(com.google.firebase:firebase-database@@19.2.1:231)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertToCustomClass(com.google.firebase:firebase-database@@19.2.1:79)
        at com.google.firebase.database.DataSnapshot.getValue(com.google.firebase:firebase-database@@19.2.1:203)
        at com.firebase.ui.database.ClassSnapshotParser.parseSnapshot(ClassSnapshotParser.java:29)
        at com.firebase.ui.database.ClassSnapshotParser.parseSnapshot(ClassSnapshotParser.java:15)
        at com.firebase.ui.common.BaseCachingSnapshotParser.parseSnapshot(BaseCachingSnapshotParser.java:36)
        at com.firebase.ui.common.BaseObservableSnapshotArray.get(BaseObservableSnapshotArray.java:52)
        at com.firebase.ui.database.FirebaseRecyclerAdapter.getItem(FirebaseRecyclerAdapter.java:109)
        at com.firebase.ui.database.FirebaseRecyclerAdapter.onBindViewHolder(FirebaseRecyclerAdapter.java:149)
        at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7065)
        at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7107)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6012)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6279)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
        at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
        at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
        at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
        at androidx.recyclerview.widget.RecyclerView.onMeasure(RecyclerView.java:3540)
        at android.view.View.measure(View.java:24710)
        at androidx.constraintlayout.widget.ConstraintLayout.internalMeasureChildren(ConstraintLayout.java:1227)
        at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java:1572)
        at android.view.View.measure(View.java:24710)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6858)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
        at android.view.View.measure(View.java:24710)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6858)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
        at android.view.View.measure(View.java:24710)
        at androidx.drawerlayout.widget.DrawerLayout.onMeasure(DrawerLayout.java:1119)
        at android.view.View.measure(View.java:24710)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6858)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
        at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:143)
        at android.view.View.measure(View.java:24710)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6858)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
2020-04-28 00:24:39.908 9023-9023/? E/AndroidRuntime:     at android.view.View.measure(View.java:24710)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6858)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
        at android.view.View.measure(View.java:24710)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6858)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
        at android.view.View.measure(View.java:24710)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6858)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
        at com.android.internal.policy.DecorView.onMeasure(DecorView.java:743)
        at android.view.View.measure(View.java:24710)
        at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:3258)
        at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:2041)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2336)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1929)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7987)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1154)
        at android.view.Choreographer.doCallbacks(Choreographer.java:977)
        at android.view.Choreographer.doFrame(Choreographer.java:893)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1139)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7682)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)

Ответы [ 2 ]

0 голосов
/ 27 апреля 2020

Когда вы нажимаете на элемент в recyclerview проходе нажатой клавиши:

    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            String key = adapter.getRef(position).getKey();

            Intent intent = new Intent(getActivity(), updateDeleteCars.class);
            intent.putExtra("make", model.getCarMake());
            intent.putExtra("type", model.getCarType());
            intent.putExtra("year", model.getCarYear());
            //here
            intent.putExtra("key", key);
            startActivity(intent);
        }
    });

Теперь вы получаете эту пройденную клавишу в своей операции обновления и выполняете обновление:

public class updateDeleteCars extends AppCompatActivity {

.........
.........

//don't use the key that you made

//use this
private String passedKey;


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


     ........
     //this is what we will use
     passedKey = getIntent().getStringExtra("key");

    ............

     }

Обновление выглядит так:

    update.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            databaseReference.child(passedKey).child("carMake").setValue(make.getText().toString());
            databaseReference.child(passedKey).child("carType").setValue(type.getText().toString());
            databaseReference.child(passedKey).child("carYear").setValue(year.getText().toString());

        }
    });
0 голосов
/ 27 апреля 2020

Этот код:

databaseReference = FirebaseDatabase.getInstance().getReference("Cars").child(userId);
key = databaseReference.getKey();

Это очень запутанный способ сказать:

key = userId;

Поэтому, когда вы делаете databaseReference.child(key)....setValue(...), вы создаете нового ребенка с помощью userId под существующим userId.


Если вы хотите обновить существующий автомобиль под узлом идентификатора пользователя, вы уже знаете ключ дочернего узла:

databaseReference.child("-M5vP3HXN5UINkvZFJ0q").child("carMake").setValue(make.getText().toString())

Если вы не знаете ключ, вам сначала нужно прочитать данные, чтобы определить дочерний ключ (и):

databaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for (DataSnapshot carSnapshot: dataSnapshot.getChildren()) {
            carSnapshot.getRef()..child("carMake").setValue(make.getText().toString());
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        throw databaseError.toException();
    }
}

for l oop здесь необходимо, потому что у вас может быть несколько дочерних узлов под узлом идентификатора пользователя. Если вы не хотите иметь несколько дочерних узлов, не вызывайте push() при добавлении данных автомобиля.


Если вы знаете уникальное значение свойства дочернего узла для обновления , вы можете использовать запрос, чтобы выбрать только эти узлы:

databaseReference
  .orderByChild("carMake")
  .equalTo("renouot")
  .addListenerForSingleValueEvent(new ValueEventListener() {
    ...

Имейте в виду, что он все равно может совпадать с несколькими дочерними узлами, поэтому for l oop необходим, как и раньше.


Последнее замечание: теперь вы звоните setValue() три раза, чтобы установить данные для автомобиля. Хотя это может дать вам правильный результат, оно, скорее всего, создаст проблемы в будущем. Для всего обновления лучше всего выполнить одну операцию записи:

HashMap<String,Object> values = new HashMap<>();
values.put("carMake", make.getText().toString());
values.put("carType", type.getText().toString());
values.put("carYear", year.getText().toString());
databaseReference.setValue(values);
...