一个很难解释的东西。
这是我在报告中遇到的错误:
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);
我认为这可能与我们将上下文插入适配器,然后在页面完成之前更改页面的方式有关,但是事实证明这没有定论。
带有适配器的粘贴容器:Adaptor
答案 0 :(得分:1)
Fragment#getContext()
可为空。当您的片段与活动分离时,此方法返回null
。该应用程序崩溃是因为您在未附加片段的情况下创建了适配器,从而导致null
传递给了构造函数。
仅在将片段附加到活动时才应调用方法showShipments
。有回调onAttach()
和onDetach()
可以帮助您检测状态。此外,isAdded()
还向您返回一个布尔值,说明是否附加了该片段。选择最方便的方式。
祝你好运!
答案 1 :(得分: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;
}
}
答案 2 :(得分:0)
您可以在适配器设置过程中检查是否为空以避免这种情况。在一个片段中,getActivity
可以sometimes return null在Fragment lifecycle的不同点上。例如,在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()
,如果该值为假,则可以从getActivity()
中获取空值。
另外,请考虑将呼叫fetchShipments()
从onCreateView
转移到onActivityCreated
。
答案 3 :(得分:0)
好像您在返回片段布局视图(myView)之前正在调用fetchShipments();
,因此在实例化适配器时它为null。
尝试:
从onCreateView()中移动fetchShipments();
并将其放在onResume()中,或覆盖onStart()并从那里调用它