我在主要活动上有2个片段,并用2个按钮替换它们之间。
第一个按钮-点亮片段。
第二个按钮-车库片段。
灯光片段-应用程序打开时创建的主要片段。
该片段包含RecyclerView,以及使用Glide从Firebase加载的图像。
问题是,当应用程序打开时,如果LightsFragment上的图像仍未加载,并且我更改为第二个片段(GarageFragment),那么当我返回LightsFragment时,应用程序崩溃-请参阅代码下方的日志。
灯适配器:
import java.util.ArrayList;
public class LightsAdapter extends RecyclerView.Adapter<LightsAdapter.LightsViewHolder> {
private Context context;
private ArrayList<Light> lights;
private OnLightImageTouchListener onLightImageTouchListener;
private int selected = -1;
private Light light;
public LightsAdapter(Context context, ArrayList<Light> lights) {
this.context = context;
this.lights = lights;
}
public void updateData(ArrayList<Light> lights) {
this.lights = lights;
notifyDataSetChanged();
}
public interface OnLightImageTouchListener {
void onLightImageTouch(int position, MotionEvent motionEvent, LightsViewHolder holder);
}
public void setOnLightImageTouchListener(OnLightImageTouchListener onLightImageTouchListener) {
this.onLightImageTouchListener = onLightImageTouchListener;
}
@NonNull
@Override
public LightsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, final int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.lights_item, parent, false);
return new LightsViewHolder(view);
}
@SuppressLint("ClickableViewAccessibility")
@Override
public void onBindViewHolder(@NonNull final LightsViewHolder holder, final int position) {
light = lights.get(position);
holder.rootItemView.setTag(position);
**//Glide - image loader.
Glide.with(context)
.load(light.getLampImageUrl())
.placeholder(R.drawable.ic_launcher_background)
.override(200, 200)
.into(holder.IVLightImage);**
setLightColor(holder, position);
//This method called from LightsFragment.
holder.rootItemView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
int position = (int) view.getTag();
selected = position;
if (onLightImageTouchListener != null) {
onLightImageTouchListener.onLightImageTouch(position, motionEvent, holder);
}
return true;
}
});
}
@Override
public int getItemCount() {
return lights.size();
}
public class LightsViewHolder extends RecyclerView.ViewHolder {
private ImageView IVLightImage;
private CardView rootItemView;
public LightsViewHolder(@NonNull View itemView) {
super(itemView);
IVLightImage = itemView.findViewById(R.id.lightImage);
rootItemView = itemView.findViewById(R.id.rootItemView);
}
}
//Open light information on bottom sheet dialog.
public void openLightInfo(int position) {
View modelBottomSheet = LayoutInflater.from(context).inflate(R.layout.lights_info_bottom_sheet, null);
BottomSheetDialog dialog = new BottomSheetDialog(context);
dialog.setContentView(modelBottomSheet);
TextView TVlightTitle = dialog.findViewById(R.id.lightTitle);
TextView TVLightDesc = dialog.findViewById(R.id.lightDesc);
TextView TVLightType = dialog.findViewById(R.id.lightType);
TVlightTitle.setText(lights.get(position).getLampTitle());
TVLightDesc.setText(lights.get(position).getLampDesc());
TVLightType.setText(String.valueOf(lights.get(position).getLampType()));
dialog.show();
}
//Set light color according to warning priority (1-4)
public void setLightColor(LightsViewHolder holder, int position) {
switch (lights.get(position).getLampType()) {
case 1:
holder.IVLightImage.setColorFilter(Color.RED);
break;
case 2:
holder.IVLightImage.setColorFilter(Color.YELLOW);
break;
case 3:
holder.IVLightImage.setColorFilter(Color.GREEN);
break;
case 4:
holder.IVLightImage.setColorFilter(Color.BLUE);
break;
}
}
}
LightsView-dataLoader:
public class LightsView {
private ArrayList<Light> lights = new ArrayList<>();
private Light light;
private FirebaseDatabase db;
private DatabaseReference allLights;
private LightsPresenter lightsPresenter;
public LightsView(ArrayList<Light> lights, Light light, LightsPresenter lightsPresenter) {
this.lights = lights;
this.light = light;
this.lightsPresenter = lightsPresenter;
}
public void loadData() {
db = FirebaseDatabase.getInstance();
allLights = db.getReference("AllLights");
allLights.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
light = dataSnapshot1.getValue(Light.class);
lights.add(light);
Log.i("LightsDataLoaded", "true " + light.getLampTitle());
}
lightsPresenter.setAdapter();
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
Log.i("LightsDataLoaded", "false ");
}
});
}
}
MainActivity-创建LightsFragment的onCreate方法:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initFunctions();
}
public void initFunctions() {
showLightsFragment();
showGreetings();
}
**public void showLightsFragment() {
getSupportFragmentManager().beginTransaction().replace(R.id.main_fragment_container, this.lightsFragment)
.commit();
}**
灯具型号:
public class Light implements Comparable<Light> {
private int lampType;
private String lampTitle;
private String lampDesc;
private String lampImageUrl;
public Light() {
}
public Light(int lampType, String lampTitle, String lampDesc, String lampImageUrl) {
this.lampType = lampType;
this.lampTitle = lampTitle;
this.lampDesc = lampDesc;
this.lampImageUrl = lampImageUrl;
}
public int getLampType() {
return lampType;
}
public void setLampType(int lampType) {
this.lampType = lampType;
}
public String getLampTitle() {
return lampTitle;
}
public void setLampTitle(String lampTitle) {
this.lampTitle = lampTitle;
}
public String getLampDesc() {
return lampDesc;
}
public void setLampDesc(String lampDesc) {
this.lampDesc = lampDesc;
}
public String getLampImageUrl() {
return lampImageUrl;
}
public void setLampImageUrl(String lampImageUrl) {
this.lampImageUrl = lampImageUrl;
}
@Override
public int compareTo(Light o) {
return Integer.compare(lampType, o.lampType);
}
}
LightsFragment:
public class LightsFragment extends Fragment implements LightsPresenter {
private RecyclerView RVLights;
private ArrayList<Light> lights = new ArrayList<>();
private Light light;
private LightsAdapter lightsAdapter;
private LightsView presenter;
private View view;
private Animation animation;
public LightsFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (view == null) {
view = inflater.inflate(R.layout.fragment_lights, container, false);
initView(view);
if (getActivity() != null) {
presenter = new LightsView(lights, light, this);
presenter.loadData();
}
}
return view;
}
//Setting adapter parameters.
@Override
public void setAdapter() {
lightsAdapter = new LightsAdapter(getActivity(), lights);
RecyclerView.LayoutManager layoutManager = new GridLayoutManager(getActivity(), 3);
RVLights.setLayoutManager(layoutManager);
RVLights.setAdapter(lightsAdapter);
lightsAdapter.setOnLightImageTouchListener(new LightsAdapter.OnLightImageTouchListener() {
@Override
public void onLightImageTouch(final int position, MotionEvent event, LightsAdapter.LightsViewHolder holder) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
animation = AnimationUtils.loadAnimation(getActivity(), R.anim.fade_in);
holder.itemView.startAnimation(animation);
Log.d("IsTouched", "positionTouchedDown " + position);
MainActivity mainActivity = (MainActivity) getActivity();
mainActivity.removeSortFragment();
break;
case MotionEvent.ACTION_UP:
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
lightsAdapter.openLightInfo(position);
lightsAdapter.notifyDataSetChanged();
}
}, 100);
Log.d("IsTouched", "positionTouchedUP" + position);
break;
}
}
});
}
//Sorting adapter by warning color ( 1-4, red - blue )
public void sortAdapter() {
Collections.sort(lights);
lightsAdapter.updateData(lights);
}
//Initializing views.
public void initView(View view) {
RVLights = view.findViewById(R.id.RVLights);
}
}
来自logcat的日志:
2019-11-12 15:51:57.939 6889-6889/com.enjoyapp.carhelper E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.enjoyapp.carhelper, PID: 6889
java.lang.NullPointerException: You cannot start a load on a not yet attached View or a Fragment where getActivity() returns null (which usually occurs when getActivity() is called before the Fragment is attached or after the Fragment is destroyed).
at com.bumptech.glide.util.Preconditions.checkNotNull(Preconditions.java:31)
at com.bumptech.glide.Glide.getRetriever(Glide.java:684)
at com.bumptech.glide.Glide.with(Glide.java:716)
at com.enjoyapp.carhelper.Adapters.LightsAdapter.onBindViewHolder(LightsAdapter.java:67)
at com.enjoyapp.carhelper.Adapters.LightsAdapter.onBindViewHolder(LightsAdapter.java:26)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6781)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6823)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5752)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6019)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5858)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5854)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2230)
at androidx.recyclerview.widget.GridLayoutManager.layoutChunk(GridLayoutManager.java:557)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1517)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:612)
at androidx.recyclerview.widget.GridLayoutManager.onLayoutChildren(GridLayoutManager.java:171)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3924)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3641)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4194)
at android.view.View.layout(View.java:20726)
at android.view.ViewGroup.layout(ViewGroup.java:6198)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:20726)
at android.view.ViewGroup.layout(ViewGroup.java:6198)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:20726)
at android.view.ViewGroup.layout(ViewGroup.java:6198)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1083)
at android.view.View.layout(View.java:20726)
at android.view.ViewGroup.layout(ViewGroup.java:6198)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:20726)
at android.view.ViewGroup.layout(ViewGroup.java:6198)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1812)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1656)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1565)
at android.view.View.layout(View.java:20726)
at android.view.ViewGroup.layout(ViewGroup.java:6198)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:20726)
at android.view.ViewGroup.layout(ViewGroup.java:6198)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1812)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1656)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1565)
at android.view.View.layout(View.java:20726)
at android.view.ViewGroup.layout(ViewGroup.java:6198)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
最佳答案
尝试在LightsFragment和该方法调用中覆盖方法“ onViewCreated”
initView(view);
然后覆盖方法“ onAttach”并在其中写入
presenter = new LightsView(lights, light, this);
presenter.loadData();
请注意,因为片段是视图而不是演示者。在这种情况下,演示者是您的LightsView。演示者采用了视图的所有逻辑,而视图则显示了演示者要执行的操作。因此,您必须在LightsView中实现“ LightsPresenter”。