Я вроде как новичок 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