Не удается получить доступ к текстовым представлениям в режиме рециркуляции, если прокрутка выходит за рамки первоначально видимого - PullRequest
1 голос
/ 13 февраля 2020

Я вроде как новичок ie здесь. Я пытаюсь использовать просмотрщик для отображения элементов в таблице SQlite. Что мне нужно сделать, так это то, что при нажатии на элемент появляется контекстное меню с просьбой выполнить одно из трех действий. Один из пунктов требует, чтобы я получил данные из одного из текстовых представлений для выбранной позиции. Он работает хорошо, когда я щелкаю элемент, который изначально доступен для просмотра, однако, если я прокручиваю вниз до элемента, который изначально не был доступен для просмотра, он падает в точке, где он пытается получить доступ к текстовому просмотру. Вот ошибка:

Попытка вызвать виртуальный метод 'android .view.View android .widget.RelativeLayout.findViewById (int)' для ссылки на пустой объект

Активность:

package com.cascadia.nutrak;

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.text.InputType;
import android.util.Log;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.text.SimpleDateFormat;
import java.util.Date;
import static com.cascadia.nutrak.FoodDbHelper.s1;


public class MyKitchen2 extends AppCompatActivity {

    SQLiteDatabase mDatabase;
    DBRecyclerViewAdapter mAdapter;

    RecyclerView myFoodDBRecView;

    String qty;
    FoodDbHelper myFoodDB;
    public String foodItemSelected;
    boolean isInserted;
    TextView idView;
    String dBaseID;

    String selPosition;




    public void gotoCupboard(View view) {

        //Create an "Intent" to go to ManageFoodActivity
        Intent myIntent = new Intent(getApplicationContext(), ManageFoodActivity.class);

        //pass info to second activity

        //myIntent.putExtra("Friend Chosen", friendList.get(i));  //pass chosen friend as a string

        //Start the intent
        startActivity(myIntent);

    }

    public void goHome(View view) {

        startActivity(new Intent(getApplicationContext(),MainActivity.class));
    }


    public void goToMngTodaysFood(View view) {

        //Create an "Intent" to go to next activity SecondActivity
        Intent myIntent = new Intent(getApplicationContext(), ManageTodaysFood2.class);

        //Start the intent
        startActivity(myIntent);

    }




    @Override

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_kitchen2);

        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);

        myFoodDB = new FoodDbHelper(this);
        mDatabase = myFoodDB.getWritableDatabase();

        myFoodDBRecView = (RecyclerView) findViewById(R.id.myFoodDBRecView);

        myFoodDBRecView.setHasFixedSize(false);
        myFoodDBRecView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));

        //Use class DBRecyclerViewAdapter to create a new adapter and Run getAllItems function to get and put the masterFoodDB into the adapter "mAdapter".
        mAdapter = new DBRecyclerViewAdapter(this, getAllItems());

        //Assign the adapter and its contents (should be the whole MF database) to the recyclerView
        myFoodDBRecView.setAdapter(mAdapter);


        itemClickSupport.addTo(myFoodDBRecView).setOnItemClickListener(

                new itemClickSupport.OnItemClickListener() {

                    @Override
                    public void onItemClicked(RecyclerView recyclerView, int position, View view) {

                    selPosition = String.valueOf(position) ;

                    registerForContextMenu(recyclerView); //This means that when touched it will popup a context menu setup below.
                    recyclerView.showContextMenuForChild(view);
                    unregisterForContextMenu(recyclerView); //This means that when touched it will popup a context menu setup below.

                    }
                }
        );

    }//End onCreate



    //Get the entire master food database and order by description
    private Cursor getAllItems() {
        return mDatabase.query(
                dBaseContract.masterFoodDB.TABLE_NAME,
                null,
                null,
                null,
                null,
                null,
                dBaseContract.masterFoodDB.MF_COL_1 + " DESC"
        );
    }


        @Override
        public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
            super.onCreateContextMenu(menu, v, menuInfo);

            getMenuInflater().inflate(R.menu.popup_menu, menu);
        }


        @Override
        public boolean onContextItemSelected(MenuItem item) {

            Log.i("The item is", String.valueOf(item));


            switch (item.getItemId()) {

                case R.id.iatethis:

                    Toast.makeText(this, "I ate this seleted", Toast.LENGTH_SHORT).show();

                    //Here we ask for a quantity
                    AlertDialog.Builder alert = new AlertDialog.Builder(this);
                    alert.setTitle(foodItemSelected);
                    alert.setMessage("Enter Quantity Consumed");

                    // Set an EditText view to get user input
                    final EditText qtyInput = new EditText(this);

                    //limit edit text to numbers only

                    qtyInput.setInputType(InputType.TYPE_CLASS_NUMBER |
                            InputType.TYPE_NUMBER_FLAG_DECIMAL |
                            InputType.TYPE_NUMBER_FLAG_SIGNED);

                    //Set alert dialog view to use
                    alert.setView(qtyInput);

                    alert.setPositiveButton("Continue", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {

                            qty = qtyInput.getText().toString();
                            Log.d("", "Pin Value : " + qty);

                            //Get todays date
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                            String date = sdf.format(new Date());

                            RecyclerView myFoodDBRecView = (RecyclerView) findViewById(R.id.myFoodDBRecView);

                            //get the child record at the positionb
                            RelativeLayout relativeLayout = (RelativeLayout) myFoodDBRecView.getChildAt(Integer.parseInt(selPosition));

                            //Get access to text view in recylcer view child
                            TextView idView = (TextView) relativeLayout.findViewById(R.id.idView);

                            dBaseID = idView.getText().toString();

                            Log.i("The position is", selPosition);
                            Log.i("The dBaseID is", dBaseID);

                            FoodDbHelper getRecordHelper = new FoodDbHelper(MyKitchen2.this);

                            //go get entire record for the selected dBaseID
                            getRecordHelper.returnAllSingleRecord2(dBaseID); //delete fooditemselected from above

                            //Debug code to make sure we have all the data from the record.
                            for (int i = 0; i <= 10; i++) {
                                Log.i("s1 " + i, " = " + s1[i]); //Verify we have all data in array
                            }
                            isInserted = myFoodDB.insertConsumedData( //run the insertConsumedData boolean method in FoodDBHelper on main database

                                    date, qty, s1[1], s1[2], s1[3], s1[4], s1[5], s1[6], s1[7], s1[8], s1[9], s1[10], s1[11] //Insert data returned in S1 into consumed table
                                    // leave out s1[0] as it is the key from mstr table
                                    //add date and qty and then data from master 1-10
                            );

                            if (isInserted = true) {

                                Toast.makeText(MyKitchen2.this, "Data inserted into todays food", Toast.LENGTH_LONG).show();


                            } else {

                                Toast.makeText(MyKitchen2.this, "Data failed to insertinto todays food", Toast.LENGTH_LONG).show();
                            }

                            return;
                        }
                    });


                    alert.setNegativeButton("Cancel",
                            new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int which) {
                                    // TODO Auto-generated method stub
                                    return;
                                }
                            });
                    alert.show();

            return true; //always when item was handled

                case R.id.viewedit:

                    Toast.makeText(this, "view/edit selected", Toast.LENGTH_SHORT).show();

                return true; //always when item was handled
                case R.id.delete:

                    Toast.makeText(this, "deleted", Toast.LENGTH_SHORT).show();


                    FoodDbHelper dbHelper = new FoodDbHelper(MyKitchen2.this);
                    // Log.i("Still Have it?", "?  " + selPosition);
                    dbHelper.remMasterSingleRecord(dBaseID); //delete fooditemselected from above

                    mAdapter = new DBRecyclerViewAdapter(this, getAllItems());
                    myFoodDBRecView.setAdapter(mAdapter);


                    Toast.makeText(MyKitchen2.this, "Item removed from Cupboard", Toast.LENGTH_SHORT).show();


                    return true; //always when item was handled

                default: //This has to be at end
                return super.onContextItemSelected(item);  //put return super inside default case


            }

        }

    //----------------------------------------------------------------------------------------------------------------------------------
    //Special functions

    //This disables the back button
    @Override
    public void onBackPressed() {}

}

Макет:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:clickable="true"
    android:focusable="true"
    android:foreground="?android:attr/selectableItemBackground"
    android:layout_width="360dp"
    android:layout_height="55dp">

    <TextView
        android:id="@+id/foodItemView"
        android:layout_width="180dp"
        android:layout_height="25dp"
        android:layout_marginLeft="0dp"
        android:layout_marginTop="0dp"
        android:gravity="left|center_vertical"
        android:textSize="16sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/descView"
        android:layout_width="180dp"
        android:layout_height="25dp"
        android:layout_alignParentTop="true"
        android:layout_marginStart="0dp"
        android:layout_marginTop="0dp"
        android:layout_toEndOf="@+id/foodItemView"
        android:gravity="left|center_vertical" />

    <TextView
        android:id="@+id/textView52"
        android:layout_width="45dp"
        android:layout_height="25dp"
        android:layout_below="@+id/foodItemView"
        android:layout_marginTop="0dp"
        android:gravity="center_horizontal|center_vertical"
        android:text="Cals" />

    <TextView
        android:id="@+id/calsView"
        android:layout_width="45dp"
        android:layout_height="25dp"
        android:layout_below="@+id/foodItemView"
        android:layout_marginStart="45dp"
        android:layout_marginTop="0dp"
        android:gravity="left|center_vertical" />

    <TextView
        android:id="@+id/textView54"
        android:layout_width="45dp"
        android:layout_height="25dp"
        android:layout_below="@+id/foodItemView"
        android:layout_marginStart="90dp"
        android:layout_marginTop="0dp"
        android:gravity="center_horizontal|center_vertical"
        android:text="Carbs" />

    <TextView
        android:id="@+id/carbsView"
        android:layout_width="45dp"
        android:layout_height="25dp"
        android:layout_below="@+id/foodItemView"
        android:layout_marginStart="135dp"
        android:layout_marginTop="0dp"
        android:gravity="left|center_vertical" />

    <TextView
        android:id="@+id/textView56"
        android:layout_width="45dp"
        android:layout_height="25dp"
        android:layout_below="@+id/descView"
        android:layout_marginStart="180dp"
        android:layout_marginLeft="50dp"
        android:layout_marginTop="0dp"
        android:gravity="center_horizontal|center_vertical"
        android:text="Prot" />

    <TextView
        android:id="@+id/protView"
        android:layout_width="45dp"
        android:layout_height="25dp"
        android:layout_below="@+id/descView"
        android:layout_marginStart="225dp"
        android:layout_marginLeft="50dp"
        android:layout_marginTop="0dp"
        android:gravity="left|center_vertical" />

    <TextView
        android:id="@+id/textView58"
        android:layout_width="45dp"
        android:layout_height="25dp"
        android:layout_below="@+id/descView"
        android:layout_marginStart="270dp"
        android:layout_marginLeft="50dp"
        android:layout_marginTop="0dp"
        android:gravity="center_horizontal|center_vertical"
        android:text="Fat" />

    <TextView
        android:id="@+id/fatView"
        android:layout_width="45dp"
        android:layout_height="25dp"
        android:layout_below="@+id/descView"
        android:layout_marginStart="315dp"
        android:layout_marginLeft="50dp"
        android:layout_marginTop="0dp"
        android:gravity="left|center_vertical" />

    <TextView
        android:id="@+id/textView60"
        android:layout_width="400dp"
        android:layout_height="5dp"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="-1dp"
        android:background="#000000"
        android:text="TextView" />

    <TextView
            android:id="@+id/idView"
            android:layout_width="50dp"
            android:layout_height="25dp"
            android:layout_marginLeft="300dp"
            android:visibility="visible" />

</RelativeLayout>

Просмотр в Recycler


package com.cascadia.nutrak;

import android.content.Context;
import android.database.Cursor;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.recyclerview.widget.RecyclerView;

public class DBRecyclerViewAdapter extends RecyclerView.Adapter<DBRecyclerViewAdapter.masterFoodViewHolder> {

    private Context mContext;
    private Cursor mCursor;


    public DBRecyclerViewAdapter(Context context, Cursor cursor) {
        mContext = context;
        mCursor = cursor;
    }


    public class masterFoodViewHolder extends RecyclerView.ViewHolder { //} implements View.OnClickListener {

        //Initialize all the text views
        public TextView idText;
        public TextView nameText;
        public TextView calsText;
        public TextView protText;
        public TextView carbsText;
        public TextView fatText;
        public TextView descText;


        //Here we fill the viewholder
        public masterFoodViewHolder(View itemView) {
            super(itemView);


            //Here we assign the listLayout.xml TextView components to the TextView variables
            idText = itemView.findViewById(R.id.idView);
            nameText = itemView.findViewById(R.id.foodItemView);
            calsText = itemView.findViewById(R.id.calsView);
            protText = itemView.findViewById(R.id.protView);
            carbsText = itemView.findViewById(R.id.carbsView);
            fatText = itemView.findViewById(R.id.fatView);
            descText = itemView.findViewById(R.id.descView);
        }
    }


        @Override
        public masterFoodViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

            //Inflate the Recycler View using mContext and listLayout.xml
            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
            View view = inflater.inflate(R.layout.listlayout, parent, false);


            return new masterFoodViewHolder(view);
        }


        @Override
        public void onBindViewHolder(masterFoodViewHolder holder, final int position) {

            //Bind your datasource, in this case SQlite dbase, to the ViewHolder

            //Cursor through all records
            if (!mCursor.moveToPosition(position)) {
                return;
            }

            //Here we are loading the dbase column values into variables
            String id = mCursor.getString(mCursor.getColumnIndex(dBaseContract.masterFoodDB.MF_ID));
            String name = mCursor.getString(mCursor.getColumnIndex(dBaseContract.masterFoodDB.MF_COL_1));
            String cals = mCursor.getString(mCursor.getColumnIndex(dBaseContract.masterFoodDB.MF_COL_2));
            String prot = mCursor.getString(mCursor.getColumnIndex(dBaseContract.masterFoodDB.MF_COL_3));
            String carbs = mCursor.getString(mCursor.getColumnIndex(dBaseContract.masterFoodDB.MF_COL_4));
            String fat = mCursor.getString(mCursor.getColumnIndex(dBaseContract.masterFoodDB.MF_COL_5));
            String desc = mCursor.getString(mCursor.getColumnIndex(dBaseContract.masterFoodDB.MF_COL_11));

            //Here we are loading the dbase columns, now in variables, into the listlayout textviews to display to user
            holder.idText.setText(id);
            holder.nameText.setText(name);
            holder.calsText.setText(cals);
            holder.protText.setText(prot);
            holder.carbsText.setText(carbs);
            holder.fatText.setText(fat);
            holder.descText.setText(desc);



        }//end onbindviewholder

        @Override
        public int getItemCount() {
            return mCursor.getCount();
        }





    //declare interface for recycler view on item click listener
    private  OnItemClicked onClick;

    //make interface like this
    public interface OnItemClicked {
        void onItemClick(final int position);
    }

    public void setOnClick(OnItemClicked onClick)
    {
        this.onClick=onClick;
    }


    }
    //end of activity



1 Ответ

0 голосов
/ 13 февраля 2020

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

mAdapter.get(position)

Трудно сказать, потому что я не вижу, о какой строке кода вы говорите

Я думаю, вы говорите об этом

  //get the child record at the positionb
                        RelativeLayout relativeLayout = (RelativeLayout) myFoodDBRecView.getChildAt(Integer.parseInt(selPosition));

                        //Get access to text view in recylcer view child
                        TextView idView = (TextView) relativeLayout.findViewById(R.id.idView);

Если это так, попробуйте

dBaseID = myFoodDBRecView.adapter.get(selPosition);

Вы не должны пытаться получить идентификатор из текстового представления, которое может или может не загружаться. Вместо этого сохраните его в адаптер или хэш-карту или что-то

...