Очень сложно объяснить.
Это ошибка, которую я получаю в своем отчете:
Attempt to invoke virtual method 'java.lang.Object android.content.Context.getSystemService(java.lang.String)' on a null object reference
Кажется, что это происходит периодически, когда вы входите в фрагмент и выходите из него. Похоже, ошибка произошла в адаптере.
Вот где это называется:
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
getActivity().setTitle("Shipments");
myView = inflater.inflate(R.layout.shipments_out_layout, container, false);
listView = myView.findViewById(R.id.listView);
fetchShipments();
return myView;
}
/**
* Fetch shipments
*/
public void fetchShipments()
{
shipmentsService.fetchFromServer(getActivity());
}
/**
* Show shipments
*/
public void showShipments(){
RealmResults<Shipment> savedShipments = shipmentsService.all();
ShipmentsAdaptor adaptor = new ShipmentsAdaptor(savedShipments, this.getContext());
listView.setAdapter(adaptor);
}
И вот тут ошибка в адаптере:
public class ShipmentsAdaptor extends ArrayAdapter<Shipment> {
private RealmResults<Shipment> dataSet;
Context mContext;
// View lookup cache
private static class ViewHolder {
TextView stockItemId;
TextView technicianName;
TextView shipmentDate;
}
public ShipmentsAdaptor(RealmResults<Shipment> data, Context context){
super(context, R.layout.shipments_out_row_item, data);
this.dataSet = data;
this.mContext = context;
}
Это конкретно эта строка: super(context, R.layout.shipments_out_row_item, data);
Я подумал, что это может быть связано с тем, как мы вставляем контекст в адаптер, а затем меняем страницу до ее завершения, но это оказалось безрезультатным.
Корзина для вставки с адаптером: Адаптер
Выложите все ошибки журнала. Пожалуйста!
Добавлена полная ошибка
Спасибо. Но ставьте и свой полноценный адаптер. Пожалуйста!
Добавил пастебин с переходником
Спасибо! Я добавил новый ответ




Fragment#getContext() допускает значение NULL. Этот метод возвращает null, когда ваш фрагмент отключается от активности. Приложение вылетает из-за того, что вы создаете адаптер, а фрагмент не прикреплен, в результате чего в конструктор передается null.
Метод showShipments следует вызывать только тогда, когда фрагмент прикреплен к активности. Есть обратные вызовы onAttach() и onDetach(), которые помогут вам определить состояние. Также isAdded() возвращает логическое выражение, прикреплен ли фрагмент или нет. Выбирайте то, что вам удобно.
Удачи!
Спасибо, имеет смысл, я буду использовать приведенный выше код, чтобы узнать, работает ли это.
onAttach не похоже на метод, который можно переопределить во фрагменте, я делаю это не в том месте
Это никак не меняет мой ответ :) Но спасибо за дополнительную информацию. Решение простое - просто убедитесь, что контекст, который вы передаете адаптеру, никогда не равен нулю.
Могу ли я получить доступ к контексту напрямую из адаптера, чтобы избавиться от необходимости передавать его через
Нет. Адаптер - это простой класс, который выполняет сопоставление данных и представлений. И ему нужен контекст, чтобы раздуть эти представления, иначе он не сможет ничего отобразить. Вам нужно получить контекст активности и передать его адаптеру. К контексту действия может получить доступ ваш фрагмент после того, как он будет прикреплен.
Попробуйте выполнить рефакторинг вашего адаптера с помощью BaseAdapter, как показано ниже.
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class ShipmentsAdaptor extends BaseAdapter {
private RealmResults<Shipment> dataSet;
private Context mContext;
// View lookup cache
private static class ViewHolder {
TextView stockItemId;
TextView technicianName;
TextView shipmentDate;
}
public ShipmentsAdaptor(RealmResults<Shipment> dataSet, Context context) {
this.dataSet = dataSet;
this.mContext = context;
}
@Override
public int getCount() {
return dataSet.size();
}
@Override
public Object getItem(int position) {
return dataSet.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
Shipment shipment = (Shipment) getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
ViewHolder viewHolder; // view lookup cache stored in tag
final View result;
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(R.layout.shipments_out_row_item, parent, false);
viewHolder.stockItemId = convertView.findViewById(R.id.stockItemId);
viewHolder.technicianName = convertView.findViewById(R.id.technicianName);
viewHolder.shipmentDate = convertView.findViewById(R.id.shipmentDate);
result = convertView;
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
result=convertView;
}
lastPosition = position; //use getItemId() instead
if (shipment != null){
viewHolder.stockItemId.setText(String.valueOf(shipment.id));
if (shipment.technician != null){
viewHolder.technicianName.setText(shipment.technician.name);
}
viewHolder.shipmentDate.setText(shipment.shippingDate);
}
// Return the completed view to render on screen
return convertView;
}
}
Спасибо, попробуем через мгновение
Вы можете проверить значение null во время настройки адаптера, чтобы избежать этого. Во фрагменте getActivity может иногда возвращает ноль в разных точках во время Жизненный цикл фрагмента. Например, в showShipments
Activity a = getActivity();
if ( a == null || a.isFinishing() ) {
// Not in a valid state to show things anyway, so just stop and exit
return;
}
ShipmentsAdaptor adaptor = new ShipmentsAdaptor(savedShipments, a);
Вы также можете проверить isAdded(), и если это неверно, вы можете получить null от getActivity().
Также рассмотрите возможность переноса вызова на fetchShipments() с onCreateView на onActivityCreated.
Похоже, вы вызываете fetchShipments(); до того, как будет возвращено представление макета фрагмента (myView), поэтому при создании экземпляра адаптера он имеет значение null.
Пытаться:
Переместите fetchShipments(); из onCreateView () и поместите его в onResume () или переопределите onStart () и вызовите его оттуда
Не имеет отношения к проблеме, но ... это должен быть адаптер, а не адаптер :)