0

超级难解释。

这是我在报告中遇到的错误:

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);

我认为这可能与我们将上下文插入适配器然后在完成之前更改页面的方式有关,但事实证明这是不确定的。

带适配器的粘贴箱:适配器

在此处输入图像描述

4

4 回答 4

1

Fragment#getContext()可以为空的。null当您的片段与活动分离时,此方法返回。应用程序崩溃是因为您在未附加片段时创建了适配器,这导致null传递给构造函数。

showShipments仅当片段附加到活动时才应调用该方法。有回调onAttach()onDetach()这将帮助您检测状态。还会isAdded()返回一个布尔值,说明是否附加了片段。选择你方便的。

祝你好运!

于 2018-07-13T14:01:43.157 回答
0

尝试使用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;
    }
}
于 2018-07-13T14:44:48.140 回答
0

您可以在适配器设置期间检查 null 以避免这种情况。在 Fragment 中,getActivity有时会在Fragment 生命周期的不同时间点返回 null。例如,在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()from onCreateViewto onActivityCreated

于 2018-07-13T15:12:57.260 回答
0

看起来您是fetchShipments();在返回片段布局视图(myView)之前调用的,因此在实例化适配器时它为空。

尝试:

从 onCreateView()移动fetchShipments();并将其放在 onResume() 或覆盖 onStart() 并从那里调用它

于 2018-07-13T15:49:40.540 回答