You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android多Fragment应用中用户绘图持久化实现问询

Alright, let's fix your drawing persistence issue step by step. The core problems with your current code are:

  1. Your FingerPath class doesn't serialize the Path object in its Parcelable implementation, so the actual drawing paths aren't being saved.
  2. You're trying to use putParcelableArray with an ArrayList, which won't work—you need to use the correct method for lists of Parcelables.
  3. You haven't added logic to restore the saved paths when the fragment is recreated.

Step 1: Fix the FingerPath Parcelable Implementation

The Path class already implements Parcelable, so we just need to add it to the serialization/deserialization flow:

import android.graphics.Path;
import android.os.Parcel;
import android.os.Parcelable;

public class FingerPath implements Parcelable {
    public int color;
    public boolean emboss;
    public boolean blur;
    public int strokeWidth;
    public Path path;

    public FingerPath(int color, boolean emboss, boolean blur, int strokeWidth, Path path) {
        this.color = color;
        this.emboss = emboss;
        this.blur = blur;
        this.strokeWidth = strokeWidth;
        this.path = path;
    }

    protected FingerPath(Parcel in) {
        color = in.readInt();
        emboss = in.readByte() != 0;
        blur = in.readByte() != 0;
        strokeWidth = in.readInt();
        // Read the Path object (it's Parcelable)
        path = in.readParcelable(Path.class.getClassLoader());
    }

    public static final Creator<FingerPath> CREATOR = new Creator<FingerPath>() {
        @Override
        public FingerPath createFromParcel(Parcel in) {
            return new FingerPath(in);
        }

        @Override
        public FingerPath[] newArray(int size) {
            return new FingerPath[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeInt(color);
        parcel.writeByte((byte) (emboss ? 1 : 0));
        parcel.writeByte((byte) (blur ? 1 : 0));
        parcel.writeInt(strokeWidth);
        // Write the Path object
        parcel.writeParcelable(path, i);
    }
}

Step 2: Update PaintView to Support Restoring Paths

Add a setter method to accept saved paths, and fix the getter to use proper generics:

// Fix the getter to avoid unchecked type warnings
public ArrayList<FingerPath> getPaths() {
    return paths;
}

// Add a setter to restore saved paths and trigger redraw
public void setPaths(ArrayList<FingerPath> paths) {
    this.paths = new ArrayList<>(paths);
    invalidate(); // Force the view to redraw with restored paths
}

Step 3: Fix Fragment State Save/Restore Logic

Use putParcelableArrayList (designed for lists of Parcelables) instead of putParcelableArray, and add code to restore paths when the fragment recreates:

import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class LineLHwFragment extends Fragment {
    private PaintView paintView;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_line_l_hw, container, false);
        paintView = v.findViewById(R.id.lineLPaintView);
        DisplayMetrics metrics = new DisplayMetrics();
        getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
        paintView.init(metrics);

        // Restore saved paths if they exist
        if (savedInstanceState != null) {
            ArrayList<FingerPath> savedPaths = savedInstanceState.getParcelableArrayList("line_paths");
            if (savedPaths != null) {
                paintView.setPaths(savedPaths);
            }
        }

        setHasOptionsMenu(true);
        return v;
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.main, menu);
        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.normal:
                paintView.normal();
                return true;
            case R.id.clear:
                paintView.clear();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        // Save the ArrayList of FingerPath using the correct method
        outState.putParcelableArrayList("line_paths", paintView.getPaths());
    }
}

Bonus: Persist Drawing Across App Restarts

If you want the drawing to stay even after the user closes and reopens the app, add file-based persistence to PaintView:

First, make FingerPath implement Serializable:

public class FingerPath implements Parcelable, Serializable {
    // ... existing code remains the same ...
}

Then add save/load methods to PaintView:

import android.content.Context;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

// Save paths to internal storage
public void savePathsToFile(Context context) {
    try {
        FileOutputStream fos = context.openFileOutput("drawing_data.dat", Context.MODE_PRIVATE);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(paths);
        oos.close();
        fos.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

// Load paths from internal storage
@SuppressWarnings("unchecked")
public void loadPathsFromFile(Context context) {
    try {
        FileInputStream fis = context.openFileInput("drawing_data.dat");
        ObjectInputStream ois = new ObjectInputStream(fis);
        paths = (ArrayList<FingerPath>) ois.readObject();
        ois.close();
        fis.close();
        invalidate();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Finally, call these methods in your fragment's lifecycle:

@Override
public void onPause() {
    super.onPause();
    paintView.savePathsToFile(getContext());
}

@Override
public void onResume() {
    super.onResume();
    paintView.loadPathsFromFile(getContext());
}

内容的提问来源于stack exchange,提问作者dan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 14:53:11