android中adapter.clear()引起的错误

解决Android Spinner清空数据问题
本文介绍如何解决Android应用中Spinner组件无法清空数据的问题。通过使用List替代数组作为数据源,实现了对Spinner绑定数据的动态更新和清除。

public class MainActivity extends Activity implements OnClickListener {
	ArrayAdapter<String> adapter;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		
		setContentView(R.layout.paomadeng);
		Spinner spinner = (Spinner) findViewById(R.id.spinner);
		
		String[] strArray = new String[]{"杭州","上海", "南京", "北京", "广州", "深圳"};
		
		adapter = new ArrayAdapter<String>(this,
				android.R.layout.simple_spinner_dropdown_item,  strArray);

		spinner.setAdapter(adapter);
		
		spinner.setOnItemSelectedListener(new OnItemSelectedListener() {

			@Override
			public void onItemSelected(AdapterView<?> parent, View view,
					int position, long id) {
					System.out.println(adapter.getItem(position));
			}

			@Override
			public void onNothingSelected(AdapterView<?> parent) {
				System.out.println("nothing selected");
			}
		});
		Button btn = (Button) findViewById(R.id.btn);
		btn.setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		adapter.clear();
	}
}

点击这里的Button,也就是执行onClick()之后,发生如下错误:

02-16 13:50:21.062: E/AndroidRuntime(29353): FATAL EXCEPTION: main
02-16 13:50:21.062: E/AndroidRuntime(29353): java.lang.UnsupportedOperationException
02-16 13:50:21.062: E/AndroidRuntime(29353): 	at java.util.AbstractList.remove(AbstractList.java:638)
02-16 13:50:21.062: E/AndroidRuntime(29353): 	at java.util.AbstractList$SimpleListIterator.remove(AbstractList.java:75)
02-16 13:50:21.062: E/AndroidRuntime(29353): 	at java.util.AbstractList.removeRange(AbstractList.java:658)
02-16 13:50:21.062: E/AndroidRuntime(29353): 	at java.util.AbstractList.clear(AbstractList.java:466)
02-16 13:50:21.062: E/AndroidRuntime(29353): 	at android.widget.ArrayAdapter.clear(ArrayAdapter.java:258)


http://stackoverflow.com/questions/10504353/adapter-clear-crashes-android-app

You are probably getting an UnsupportedOperationException, right? This is because the adapters get initialised with an array of objects, which it interally converts to an AbstractList, which cannot be modified.

To solve your problem, you simply need to feed something that implements the List<?> interface to the adapter. Example:

含义就是这里如果使用数组传递到Adapter的话,则它会将这个转化为AbstractList,而这个AbstractList是不可以修改的。

public ArrayAdapter(Context context, int resource, T[] objects) {
        init(context, resource, 0, Arrays.asList(objects));
    }

可以看到这里的源码是调用了Arrays.asList(),我们知道这个Arrays.asList()会返回一个不可修改的ArrayList,而且这个ArrayList是Arrays里面的。

正确的方式如下:

public class MainActivity extends Activity implements OnClickListener {
	ArrayAdapter<String> adapter;
	
	List<String> datas = new ArrayList<String>();
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		
		setContentView(R.layout.paomadeng);
		Spinner spinner = (Spinner) findViewById(R.id.spinner);
		datas.add("杭州");
		datas.add("上海");
		datas.add("南京");
		datas.add("北京");
		datas.add("广州");
		datas.add("深圳");
		
		adapter = new ArrayAdapter<String>(this,
				android.R.layout.simple_spinner_dropdown_item,  datas);

		spinner.setAdapter(adapter);
		
		spinner.setOnItemSelectedListener(new OnItemSelectedListener() {

			@Override
			public void onItemSelected(AdapterView<?> parent, View view,
					int position, long id) {
					System.out.println(adapter.getItem(position));
			}

			@Override
			public void onNothingSelected(AdapterView<?> parent) {
				System.out.println("nothing selected");
			}
		});
		Button btn = (Button) findViewById(R.id.btn);
		btn.setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		datas.clear();
		adapter.notifyDataSetChanged();
	}
}



package com.dosen.watchtest.activity; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.media.Ringtone; import android.media.RingtoneManager; import android.net.Uri; import android.os.Bundle; import android.provider.Settings; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; import com.dosen.watchtest.R; import com.dosen.watchtest.widget.WatchListView; import java.util.ArrayList; import java.util.List; /** * Created by Daisy */ public class RingtonePickerActivity extends SecondaryActivity { private static final String TAG = "RingtonePickerActivity"; public static void start(Context context) { Intent starter = new Intent(context, RingtonePickerActivity.class); context.startActivity(starter); } private WatchListView watchListView; private RingtoneAdapter adapter; private List<RingtoneItem> ringtoneItems = new ArrayList<>(); private Ringtone currentRingtone; private int selectedPosition = -1; private Uri currentRingtoneUri; private Cursor cursor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_ringtone_picker); currentRingtoneUri = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_RINGTONE); watchListView = findViewById(R.id.ringtone_list); getSystemRingtones(); adapter = new RingtoneAdapter(this, ringtoneItems); watchListView.setAdapter(adapter); watchListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) { handleRingtoneSelection(position); } }); setDefaultSelection(); } private class RingtoneAdapter extends BaseAdapter { private final Context context; private final List<RingtoneItem> items; public RingtoneAdapter(Context context, List<RingtoneItem> items) { this.context = context; this.items = items; } @Override public int getCount() { return items.size(); } @Override public Object getItem(int position) { return items.get(position); } @Override public long getItemId(int position) { return position; } class ViewHolder { TextView tvName; ImageView ivSelected; } @Override public View getView(int position, View view, ViewGroup viewGroup) { ViewHolder holder; if (view == null) { view = LayoutInflater.from(context).inflate(R.layout.ringtone_list_item, viewGroup, false); holder = new ViewHolder(); holder.tvName = view.findViewById(R.id.tv_ringtone_name); holder.ivSelected = view.findViewById(R.id.iv_ringtone_selected); view.setTag(holder); } else { holder = (ViewHolder) view.getTag(); } RingtoneItem item = items.get(position); holder.tvName.setText(item.title); if (item.selected) { holder.tvName.setTextColor(getResources().getColor(R.color.white)); holder.ivSelected.setImageResource(R.drawable.ic_radio_button_checked); } else { holder.tvName.setTextColor(getResources().getColor(R.color.text_hui)); holder.ivSelected.setImageResource(R.drawable.ic_radio_button_unchecked); } return view; } } /** * 获取系统铃声 */ private void getSystemRingtones() { ringtoneItems.clear(); RingtoneManager manager = new RingtoneManager(this); manager.setType(RingtoneManager.TYPE_RINGTONE); cursor = manager.getCursor(); if (cursor != null && cursor.moveToFirst()) { do { String title = cursor.getString(RingtoneManager.TITLE_COLUMN_INDEX); Uri uri = manager.getRingtoneUri(cursor.getPosition()); ringtoneItems.add(new RingtoneItem(title, uri)); } while (cursor.moveToNext()); cursor.close(); } } /** * 查找当前铃声在列表中的位置 */ private void setDefaultSelection() { for (int i = 0; i < ringtoneItems.size(); i++) { if (ringtoneItems.get(i).uri.equals(currentRingtoneUri)) { selectedPosition = i; ringtoneItems.get(i).selected = true; break; } } adapter.notifyDataSetChanged(); } /** * 设置选中的铃声 */ private void handleRingtoneSelection(int position) { RingtoneItem selectedItem = ringtoneItems.get(position); // 停止当前播放的铃声 if (currentRingtone != null && currentRingtone.isPlaying()) { currentRingtone.stop(); } // (重新)播放选中的铃声 currentRingtone = RingtoneManager.getRingtone(this, selectedItem.uri); currentRingtone.play(); // 更新选中状态 if (selectedPosition != -1) { ringtoneItems.get(selectedPosition).selected = false; } selectedItem.selected = true; selectedPosition = position; setAsDefaultRingtone(selectedItem.uri); adapter.notifyDataSetChanged(); } /** * 设置为系统默认铃声 * * @param uri 铃声Uri */ private void setAsDefaultRingtone(Uri uri) { try { RingtoneManager.setActualDefaultRingtoneUri( this, RingtoneManager.TYPE_RINGTONE, uri ); Log.d(TAG, "Ringtone set successfully: " + uri.toString()); } catch (SecurityException e) { Log.e(TAG, "Failed to set ringtone: " + e.getMessage()); // 处理权限问题 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { if (!Settings.System.canWrite(this)) { // 请求写入设置权限 Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS); intent.setData(Uri.parse("package:" + getPackageName())); startActivity(intent); } } } catch (Exception e) { Log.e(TAG, "Exception setting ringtone: " + e.getMessage()); } } /** * 铃声项数据类 * * @title 铃声名称 * @uri 铃声Uri * @selected 是否选中 */ private static class RingtoneItem { String title; Uri uri; boolean selected; public RingtoneItem(String title, Uri uri) { this.title = title; this.uri = uri; this.selected = false; } } @Override protected void onDestroy() { super.onDestroy(); if (currentRingtone != null && currentRingtone.isPlaying()) { currentRingtone.stop(); } if (cursor != null) { cursor.close(); } } } java Android,上述代码出现了Android StaleDataException: Attempted to access a cursor after it has been closed 的报错,请帮忙优化修改
最新发布
07-19
AndroidManifest.xml:<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.diaryapp"> <uses-feature android:name="android.hardware.camera" android:required="false" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.CAMERA" /> <application android:allowBackup="true" android:hardwareAccelerated="true" android:largeHeap="true" android:requestLegacyExternalStorage="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.HelloWorld"> <activity android:name=".MainActivity" android:label="@string/title_activity_main" android:exported="false" /> <activity android:name=".DiaryActivity" android:label="@string/title_activity_diary" android:exported="false" /> <activity android:name=".RegisterActivity" android:label="@string/title_activity_register" android:exported="false" /> <activity android:name=".LoginActivity" android:label="@string/title_activity_login" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> DiaryAdapter: package com.example.diaryapp.adapters; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.example.diaryapp.utils.GlideEngine; import com.example.diaryapp.DiaryActivity; import com.example.diaryapp.R; import com.example.diaryapp.models.Diary; import java.util.List; public class DiaryAdapter extends RecyclerView.Adapter<DiaryAdapter.DiaryViewHolder> { private Context context; private List<Diary> diaryList; private int userId; public DiaryAdapter(Context context,List<Diary> diaryList,int userId){ this.context=context; this.diaryList=diaryList; this.userId=userId; // 通过构造函数传递 userId } // 当数据更新时调用此方法 @SuppressLint("NotifyDataSetChanged") public void updateDiaries(List<Diary> newDiaries){ this.diaryList.clear(); this.diaryList.addAll(newDiaries); notifyDataSetChanged(); } @NonNull @Override public DiaryAdapter.DiaryViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view= LayoutInflater.from(context).inflate(R.layout.item_diary,parent,false); return new DiaryViewHolder(view); } // 绑定视图持有者方法 @Override public void onBindViewHolder(@NonNull DiaryAdapter.DiaryViewHolder holder, int position) { Diary diary=diaryList.get(position); holder.tvTitle.setText(diary.getTitle()); holder.tvDate.setText(diary.getDate()); holder.tvContent.setText(diary.getContent()); holder.tvWordCount.setText("字数:" + diary.getContent().length()); if (diary.getImagePath() != null && !diary.getImagePath().isEmpty()) { GlideEngine engine = GlideEngine.createGlideEngine(); engine.loadImage(context,diary.getImagePath(),holder.ivImage); } else { holder.ivImage.setBackgroundColor(context.getResources().getColor(android.R.color.darker_gray)); } holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent=new Intent(context, DiaryActivity.class); intent.putExtra("diaryId",diary.getId()); intent.putExtra("userId",userId); // 确保传递正确的 userId context.startActivities(new Intent[]{intent}); } }); } @Override public int getItemCount() { return diaryList.size(); } public static class DiaryViewHolder extends RecyclerView.ViewHolder { private TextView tvTitle,tvDate,tvContent,tvWordCount; private ImageView ivImage; public DiaryViewHolder(@NonNull View itemView) { super(itemView); tvTitle=itemView.findViewById(R.id.tvTitle); tvDate=itemView.findViewById(R.id.tvDate); tvContent=itemView.findViewById(R.id.tvContent); ivImage=itemView.findViewById(R.id.ivImage); tvWordCount=itemView.findViewById(R.id.tvWordCount); } } } Diary:package com.example.diaryapp.models; public class Diary { private int id; private String title; private String content; private String date; private String imagePath; public Diary(){} public int getId() { return id; } public void setId(int id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } public String getImagePath() { return imagePath; } public void setImagePath(String imagePath) { this.imagePath = imagePath; } } DatabaseHelper:package com.example.diaryapp.utils; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; import com.example.diaryapp.models.Diary; import java.util.ArrayList; import java.util.List; public class DatabaseHelper extends SQLiteOpenHelper { //数据库信息 private static final String DATABASE_NAME = "DiaryApp.db"; private static final int DATABASE_VERSION = 1; //用户表信息 private static final String TABLE_USER = "user"; private static final String COLUMN_USER_ID = "id"; private static final String COLUMN_USER_USERNAME = "username"; private static final String COLUMN_USER_PASSWORD = "password"; //日记表信息 private static final String TABLE_DIARY = "diary"; private static final String COLUMN_DIARY_ID = "id"; private static final String COLUMN_DIARY_USER_ID = "user_id"; private static final String COLUMN_DIARY_TITLE = "title"; private static final String COLUMN_DIARY_CONTENT = "content"; private static final String COLUMN_DIARY_DATE = "date"; private static final String COLUMN_DIARY_IMAGE_PATH = "image_path"; public DatabaseHelper(Context context) { super(context, DATABASE_NAME,null,DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { //创建用户表 String createUserTable = "CREATE TABLE " + TABLE_USER + " (" + COLUMN_USER_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + COLUMN_USER_USERNAME + " TEXT UNIQUE, " + COLUMN_USER_PASSWORD + " TEXT)"; db.execSQL(createUserTable); //创建日记表 String createDiaryTable = "CREATE TABLE " + TABLE_DIARY + " (" + COLUMN_DIARY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + COLUMN_DIARY_USER_ID + " INTEGER, " + COLUMN_DIARY_TITLE + " TEXT, " + COLUMN_DIARY_CONTENT + " TEXT, " + COLUMN_DIARY_DATE + " TEXT, " + COLUMN_DIARY_IMAGE_PATH + " TEXT)"; db.execSQL(createDiaryTable); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { //升级数据库时的操作 db.execSQL("DROP TABLE IF EXISTS " + TABLE_USER); db.execSQL("DROP TABLE IF EXISTS " + TABLE_DIARY); onCreate(db); } //用户相关操作 public long addUser(String username,String password){ SQLiteDatabase db = null; try { db=this.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(COLUMN_USER_USERNAME, username); values.put(COLUMN_USER_PASSWORD,password); return db.insert(TABLE_USER,null,values); }catch (Exception e){ e.printStackTrace(); return -1; }finally { if (db!=null){ db.close(); } } } public boolean checkUser(String username, String password){ SQLiteDatabase db = null; Cursor cursor = null; boolean exists = false; try { db=this.getReadableDatabase(); cursor = db.rawQuery( "SELECT * FROM " + TABLE_USER + " WHERE " + COLUMN_USER_USERNAME + "=? AND " + COLUMN_USER_PASSWORD + "=?", new String[]{username,password} ); exists = cursor.getCount() > 0; }catch (Exception e){ e.printStackTrace(); }finally { if (cursor != null){ cursor.close(); } if (db!=null){ db.close(); } } return exists; // Cursor cursor = db.rawQuery( // "SELECT * FROM " + TABLE_USER + " WHERE " + // COLUMN_USER_USERNAME + "=? AND " + COLUMN_USER_PASSWORD + "=?", // new String[]{username,password} // ); // boolean exists = cursor.getCount() > 0; // Log.d("DatabaseHelper","checkUser: username=" + username + ", exists=" + exists); // cursor.close(); // return exists; } public int getUserId(String username){ SQLiteDatabase db = null; Cursor cursor=null; int userId=-1; try { db = this.getReadableDatabase(); cursor = db.rawQuery( "SELECT " + COLUMN_USER_ID + " FROM " + TABLE_USER + " WHERE " + COLUMN_USER_USERNAME + "=?", new String[]{username} ); if (cursor.moveToFirst()) { // 如果cursor不为空且移动到第一条记录,获取用户ID userId = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_USER_ID)); } }catch (Exception e){ e.printStackTrace(); }finally { if (cursor!=null){ cursor.close(); } if (db!=null){ db.close(); } } return userId; } //日记相关操作 public long addDiary(int userId, Diary diary){ SQLiteDatabase db = getWritableDatabase(); try { db.beginTransaction(); ContentValues values = new ContentValues(); values.put(COLUMN_DIARY_USER_ID, userId); values.put(COLUMN_DIARY_TITLE,diary.getTitle()); values.put(COLUMN_DIARY_CONTENT,diary.getContent()); values.put(COLUMN_DIARY_DATE,diary.getDate()); values.put(COLUMN_DIARY_IMAGE_PATH,diary.getImagePath()); long result = db.insert(TABLE_DIARY,null,values); db.setTransactionSuccessful(); return result; }catch (Exception e){ e.printStackTrace(); return -1; }finally { db.endTransaction(); // if (db != null){ // db.endTransaction(); // db.close(); // } } } public List<Diary> getDiariesByUserId(int userId){ List<Diary> diaries = new ArrayList<>(); SQLiteDatabase db = getReadableDatabase(); Cursor cursor = null; try { db = this.getReadableDatabase(); cursor = db.rawQuery( "SELECT * FROM " + TABLE_DIARY + " WHERE " + COLUMN_DIARY_USER_ID + "=? ORDER BY " + COLUMN_DIARY_DATE + " DESC", new String[]{String.valueOf(userId)} ); while (cursor.moveToNext()) { Diary diary = new Diary(); diary.setId(cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_DIARY_ID))); diary.setTitle(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_TITLE))); diary.setContent(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_CONTENT))); diary.setDate(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_DATE))); diary.setImagePath(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_IMAGE_PATH))); diaries.add(diary); } }catch (Exception e){ e.printStackTrace(); }finally { if (cursor != null){ cursor.close(); } // if (db != null){ // db.close(); // } } return diaries; } public Diary getDiaryById(int diaryId){ SQLiteDatabase db = getReadableDatabase(); Cursor cursor = null; try { db = this.getReadableDatabase(); cursor = db.rawQuery( "SELECT * FROM " + TABLE_DIARY + " WHERE " + COLUMN_DIARY_ID + "=?", new String[]{String.valueOf(diaryId)} ); if (cursor.moveToFirst()) { Diary diary = new Diary(); diary.setId(cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_DIARY_ID))); diary.setTitle(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_TITLE))); diary.setContent(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_CONTENT))); diary.setDate(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_DATE))); diary.setImagePath(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DIARY_IMAGE_PATH))); return diary; } }catch (Exception e){ e.printStackTrace(); }finally { if (cursor != null){ cursor.close(); } // if (db != null){ //// db.close(); // 确保关闭数据库连接 // } } // cursor.close(); return null; } public long updateDiary(Diary diary){ SQLiteDatabase db = getWritableDatabase(); try { ContentValues values = new ContentValues(); values.put(COLUMN_DIARY_TITLE,diary.getTitle()); values.put(COLUMN_DIARY_CONTENT,diary.getContent()); values.put(COLUMN_DIARY_DATE,diary.getDate()); values.put(COLUMN_DIARY_IMAGE_PATH,diary.getImagePath()); return db.update(TABLE_DIARY, values, COLUMN_DIARY_ID + "=?", new String[]{String.valueOf(diary.getId())}); // db.close(); // 确保关闭数据库连接 // Log.d("DatabaseHelper","updateDiary: result=" + result); //调试日志 // return result; }catch (Exception e){ e.printStackTrace(); return -1; }finally { // if (db != null){ // db.close(); // } } } public void deleteDiary(int diaryId) { SQLiteDatabase db = getWritableDatabase(); try { db.beginTransaction(); db.delete(TABLE_DIARY, COLUMN_DIARY_ID + "=?", new String[]{ String.valueOf(diaryId) }); db.setTransactionSuccessful(); }catch (Exception e){ e.printStackTrace(); }finally { db.endTransaction(); } // finally { // if (db != null){ // db.close(); // } } // int result=db.delete(TABLE_DIARY, // COLUMN_DIARY_ID + "=?", // new String[]{String.valueOf(diaryId)}); // db.close(); // 确保关闭数据库连接 // Log.d("DatabaseHelper","deleteDiary: result=" + result);//调试日志 // } } GlideEngine:package com.example.diaryapp.utils; import android.content.Context; import android.widget.ImageView; import com.bumptech.glide.Glide; import com.bumptech.glide.load.resource.bitmap.CenterCrop; import com.bumptech.glide.load.resource.bitmap.RoundedCorners; import com.example.diaryapp.R; import com.luck.picture.lib.engine.ImageEngine; import com.luck.picture.lib.utils.ActivityCompatHelper; public class GlideEngine implements ImageEngine { @Override public void loadImage(Context context, String url, ImageView imageView) { if (!ActivityCompatHelper.assertValidRequest(context)) { return; } try { Glide.with(context) .load(url) .into(imageView); } catch (Exception e) { e.printStackTrace(); imageView.setBackgroundColor(context.getResources().getColor(android.R.color.darker_gray)); } } @Override public void loadImage(Context context, ImageView imageView, String url, int maxWidth, int maxHeight) { if (!ActivityCompatHelper.assertValidRequest(context)) { return; } Glide.with(context) .load(url) .override(maxWidth, maxHeight) .into(imageView); } @Override public void loadAlbumCover(Context context, String url, ImageView imageView) { if (!ActivityCompatHelper.assertValidRequest(context)) { return; } Glide.with(context) .asBitmap() .load(url) .override(180, 180) .sizeMultiplier(0.5f) .transform(new CenterCrop(), new RoundedCorners(8)) .placeholder(R.drawable.ic_launcher_background) .into(imageView); } @Override public void loadGridImage(Context context, String url, ImageView imageView) { if (!ActivityCompatHelper.assertValidRequest(context)) { return; } Glide.with(context) .load(url) .override(200, 200) .centerCrop() .placeholder(R.drawable.ic_launcher_background) .into(imageView); } @Override public void pauseRequests(Context context) { Glide.with(context).pauseRequests(); } @Override public void resumeRequests(Context context) { Glide.with(context).resumeRequests(); } private GlideEngine() { } private static final class InstanceHolder { static final GlideEngine instance = new GlideEngine(); } public static GlideEngine createGlideEngine() { return InstanceHolder.instance; } }DiaryActivity:package com.example.diaryapp; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import com.example.diaryapp.models.Diary; import com.example.diaryapp.utils.DatabaseHelper; import com.example.diaryapp.utils.GlideEngine; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Date; public class DiaryActivity extends AppCompatActivity { // 声明界面组件和相关变量 private EditText etTitle,etContent; private TextView tvDate; private ImageView ivImage; private Button btnSave,btnDelete,btnAddImage; private DatabaseHelper dbHelper; private int userId; private int diaryId = -1; private String imagePath; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_diary);// 设置布局文件 // 获取传递过来的用户ID和日记ID userId = getIntent().getIntExtra("userId",-1); diaryId = getIntent().getIntExtra("diaryId",-1); if (userId == -1){ // 检查用户ID是否有效 // 用户ID无效,可能是登录流程的问题 Toast.makeText(this, "用户ID无效", Toast.LENGTH_SHORT).show(); finish(); return; } // 初始化界面组件 initView(); // 如果是编辑日记,加载日记内容 if (diaryId != -1){ Diary diary=dbHelper.getDiaryById(diaryId); if (diary != null){ etTitle.setText(diary.getTitle()); // 设置日记标题 etContent.setText(diary.getContent()); // 设置日记内容 tvDate.setText(diary.getDate()); // 设置日记日期 imagePath=diary.getImagePath(); // 获取图片路径 if (imagePath != null && !imagePath.isEmpty()) { try { // 使用Glide加载图片 GlideEngine engine = GlideEngine.createGlideEngine(); engine.loadImage(this, imagePath, ivImage); } catch (Exception e) { e.printStackTrace(); ivImage.setBackgroundColor(getResources().getColor(android.R.color.darker_gray)); // 设置默认背景 } } // 显示删除按钮 btnDelete.setVisibility(View.VISIBLE); }else { // 日记ID无效,可能是数据库查询的问题 Toast.makeText(this, "日记ID无效", Toast.LENGTH_SHORT).show(); finish(); } }else { // 设置当前日期 tvDate.setText(getCurrentDate()); } // 添加图片按钮监听 btnAddImage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //selectImage(); // 改:if (!view.isEnabled() || !view.isClickable()){ // return; // } showImageOptions(); // 显示添加图片选项 } }); // 保存按钮监听 btnSave.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 改:if (!view.isEnabled() || !view.isClickable()){ // return; // } saveDiary(); // 保存日记 } }); // 删除按钮监听 btnDelete.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 改:if (!view.isEnabled() || !view.isClickable()){ // return; // } deleteDiary(); // 删除日记 } }); } // private void selectImage() { // // 创建选择图片的Intent // Intent pickIntent=new Intent(Intent.ACTION_GET_CONTENT); // pickIntent.setType("image/*"); // // // 创建拍照的Intent // Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // if (captureIntent.resolveActivity(getPackageManager()) != null) { // startActivityForResult(captureIntent,2); // } // //intent.setAction(Intent.ACTION_GET_CONTENT); // startActivityForResult(pickIntent,1); // } private void showImageOptions() { // 创建弹出菜单,提供两个选项:从图库选择和拍照 String[] options = {"从图库选择","拍照"}; new AlertDialog.Builder(this) .setTitle("添加图片") .setItems(options,(dialog,which) -> { if (which == 0){ //从图库选择 Intent pickIntent = new Intent(Intent.ACTION_GET_CONTENT); pickIntent.setType("image/*"); startActivityForResult(pickIntent,1); }else if (which == 1){ //拍照 Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (captureIntent.resolveActivity(getPackageManager()) != null){ startActivityForResult(captureIntent,2); }else { Toast.makeText(DiaryActivity.this, "无法调用摄像头", Toast.LENGTH_SHORT).show(); } } }) .show(); } private void saveDiary() { String title=etTitle.getText().toString().trim(); String content=etContent.getText().toString().trim(); String date=tvDate.getText().toString(); if (title.isEmpty() || content.isEmpty()){ // 检查输入是否为空 return; } Diary diary=new Diary(); diary.setTitle(title); diary.setContent(content); diary.setDate(date); diary.setImagePath(imagePath); // 确保图片路径不为空 if (diaryId != -1){ diary.setId(diaryId); dbHelper.updateDiary(diary); // 更新日记 }else { dbHelper.addDiary(userId,diary); // 添加新日记 } //返回主界面 Intent resultIntent = new Intent(); setResult(RESULT_OK,resultIntent); finish(); } private void deleteDiary() { // //删除日记 // dbHelper.deleteDiary(diaryId); new AlertDialog.Builder(this) .setTitle("确认删除") .setMessage("确定要删除这篇日记吗?") .setPositiveButton("删除", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // 使用独立的 DatabaseHelper 实例执行删除操作 DatabaseHelper helper=new DatabaseHelper(DiaryActivity.this); helper.deleteDiary(diaryId); // dbHelper.deleteDiary(diaryId); // 删除日记 // 设置结果码为RESULT_OK,表示操作成功,返回主界面MainActivity Intent resultIntent = new Intent(); setResult(RESULT_OK,resultIntent); finish(); } }) .setNegativeButton("取消",null) .show(); } @Override protected void onDestroy() { super.onDestroy(); // 释放可能持有的资源 if (btnSave!=null){ btnSave.setOnClickListener(null); } if (btnDelete!=null){ btnDelete.setOnClickListener(null); } if (btnAddImage!=null){ btnAddImage.setOnClickListener(null); } } @Override protected void onPause() { super.onPause(); // 暂停时释放资源 if (isFinishing()) { // 清理可能的临时资源 } } @Override protected void onResume() { super.onResume(); // 恢复时重新初始化资源 } private String getCurrentDate(){ // 返回当前日期的字符串表示 return new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); } protected void onActivityResult(int requestCode,int resultCode,Intent data){ super.onActivityResult(requestCode,resultCode,data); if (isFinishing() || isDestroyed()){ return; } // 确保调用super.onActivityResult if (requestCode == 1 && resultCode == RESULT_OK && data != null){ // 处理从图库选择的图片 Uri selectedImage = data.getData(); if (selectedImage != null) { // 检查selectedImage是否为null try { // 将图片保存到应用私有目录 Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), selectedImage); String filename = "diary_image_" + System.currentTimeMillis() + ".jpg"; File file = new File(getExternalFilesDir(null), filename); // File fileDir = getExternalFilesDir(null); // if (fileDir != null && !fileDir.exists()){ // fileDir.mkdir(); // } // File file = new File(fileDir,filename); FileOutputStream fos = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); fos.flush(); fos.close(); imagePath = file.getAbsolutePath(); // 改:ivImage.setImageBitmap(bitmap); // 显示图片 // 使用Glide加载图片 GlideEngine engine = GlideEngine.createGlideEngine(); engine.loadImage(this, imagePath, ivImage); } catch (IOException e) { e.printStackTrace(); //改: ivImage.setBackgroundColor(getResources().getColor(android.R.color.darker_gray)); } } // Glide.with(this).load(imagePath).into(ivImage); // }catch (IOException e){ // e.printStackTrace(); // } }else if (requestCode == 2 && resultCode == RESULT_OK && data != null){ //处理拍照结果 Bundle extras = data.getExtras(); Bitmap imageBitmap = (Bitmap) extras.get("data"); if (extras != null) { // 检查extras是否为null // Bitmap imageBitmap = (Bitmap) extras.get("data"); if (imageBitmap != null) {// 检查photo是否为null try { String filename = "diary_image_" + System.currentTimeMillis() + ".jpg"; File file = new File(getExternalFilesDir(null), filename); FileOutputStream fos = new FileOutputStream(file); imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); fos.flush(); fos.close(); imagePath = file.getAbsolutePath(); // 改:ivImage.setImageBitmap(imageBitmap); // 显示图片 // 使用Glide加载图片 GlideEngine engine = GlideEngine.createGlideEngine(); engine.loadImage(this, imagePath, ivImage); } catch (IOException e) { e.printStackTrace(); ivImage.setBackgroundColor(getResources().getColor(android.R.color.darker_gray)); } } } } } private void initView() { // 初始化界面组件 etTitle=findViewById(R.id.etTitle); etContent=findViewById(R.id.etContent); tvDate=findViewById(R.id.tvDate); ivImage=findViewById(R.id.ivImage); btnAddImage=findViewById(R.id.btnAddImage); btnSave=findViewById(R.id.btnSave); btnDelete=findViewById(R.id.btnDelete); dbHelper=new DatabaseHelper(this); // 初始化数据库助手 // userId=getIntent().getIntExtra("userId",-1); // diaryId=getIntent().getIntExtra("diaryId",-1); } } LoginActivity:package com.example.diaryapp; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.Toast; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import com.example.diaryapp.utils.DatabaseHelper; public class LoginActivity extends AppCompatActivity { private EditText etUsername,etPassword; private CheckBox cbRemember; private DatabaseHelper dbHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_login); // 初始化界面组件 initView(); // 获取SharedPreferences中的保存信息 SharedPreferences prefs=getSharedPreferences("DiaryApp",MODE_PRIVATE); String username=prefs.getString("username",""); String password=prefs.getString("password",""); // 如果用户名存在但密码不存在,删除用户名 if (username.isEmpty() || password.isEmpty()){ prefs.edit().remove("username").remove("password").apply(); } boolean remember=prefs.getBoolean("remember",false); etUsername.setText(username); etPassword.setText(password); cbRemember.setChecked(remember); // 登录按钮监听 Button btnLogin=findViewById(R.id.btnLogin); btnLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { login(); } }); // 注册按钮监听 Button btnRegister=findViewById(R.id.btnRegister); btnRegister.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent=new Intent(LoginActivity.this, RegisterActivity.class); startActivity(intent); } }); } private void login() { String username=etUsername.getText().toString().trim(); String password=etPassword.getText().toString().trim(); boolean remember=cbRemember.isChecked(); // 验证输入 if (username.isEmpty() || password.isEmpty()){ Toast.makeText(this, "用户名和密码不能为空", Toast.LENGTH_SHORT).show(); return; } // 保存登录信息到SharedPreferences SharedPreferences prefs=getSharedPreferences("DiaryApp",MODE_PRIVATE); SharedPreferences.Editor editor=prefs.edit(); // 如果记住密码被勾选,则保存密码;否则清空密码 if (remember){ editor.putString("username",username); editor.putString("password",password); }else { // editor.remove("username"); editor.remove("password"); // 确保未勾选时清空密码 } editor.putBoolean("remember",remember); editor.apply(); // 验证用户 if (dbHelper.checkUser(username,password)){ Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show(); Intent intent=new Intent(LoginActivity.this,MainActivity.class); intent.putExtra("username",username); startActivity(intent); finish(); // 关闭登录界面,避免返回时重复登录 }else { Toast.makeText(this, "用户名或密码错误", Toast.LENGTH_SHORT).show(); } } private void initView() { // 初始化界面组件 etUsername=findViewById(R.id.etUsername); etPassword=findViewById(R.id.etPassword); cbRemember=findViewById(R.id.cbRemember); dbHelper=new DatabaseHelper(this); } }MainActivity:package com.example.diaryapp; import android.annotation.SuppressLint; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.Toast; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.example.diaryapp.adapters.DiaryAdapter; import com.example.diaryapp.models.Diary; import com.example.diaryapp.utils.DatabaseHelper; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private RecyclerView rvDiaryList; private DiaryAdapter diaryAdapter; private List<Diary> diaryList; private DatabaseHelper dbHelper; private String username; private int userId; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); dbHelper=new DatabaseHelper(this); // 获取传递过来的用户名 username=getIntent().getStringExtra("username"); if (username == null){ // 用户名为空,可能是登录流程的问题 Toast.makeText(this, "用户名为空", Toast.LENGTH_SHORT).show(); finish(); return; } userId=dbHelper.getUserId(username); if (userId == -1){ // 用户ID无效,可能是数据库查询的问题 Toast.makeText(this, "用户ID无效", Toast.LENGTH_SHORT).show(); finish(); return; } // 初始化界面组件 initView(); // 加载日记 loadDiaries(); // 添加日记按钮监听 Button btnAddDiary=findViewById(R.id.btnAddDiary); // 在添加日记的按钮点击事件中 btnAddDiary.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent=new Intent(MainActivity.this,DiaryActivity.class); intent.putExtra("userId",userId); startActivityForResult(intent,1); } }); } protected void onActivityResult(int requestCode,int resultCode,Intent data){ super.onActivityResult(requestCode,resultCode,data); if (requestCode == 1 && resultCode == RESULT_OK){ // List<Diary> diaries = dbHelper.getDiariesByUserId(userId); // diaryAdapter.updateDiaries(diaries); //更新适配器数据 loadDiaries(); // 刷新日记列表 } } @SuppressLint("NotifyDataSetChanged") private void loadDiaries() { diaryList.clear(); // 清空当前列表 diaryList.addAll(dbHelper.getDiariesByUserId(userId)); // 从数据库重新获取数据 diaryAdapter.notifyDataSetChanged(); // 通知适配器数据已更改 } private void initView() { rvDiaryList=findViewById(R.id.rvDiaryList); rvDiaryList.setLayoutManager(new LinearLayoutManager(this)); diaryList=new ArrayList<>(); // 确保传递 userId 给 DiaryAdapter diaryAdapter=new DiaryAdapter(this,diaryList,userId); rvDiaryList.setAdapter(diaryAdapter); } }RegisterActivity:package com.example.diaryapp; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import com.example.diaryapp.utils.DatabaseHelper; public class RegisterActivity extends AppCompatActivity { private EditText etUsername,etPassword,etConfirmPassword; private Button btnRegister; private DatabaseHelper dbHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_register); // 初始化界面组件 initView(); // 注册按钮监听 btnRegister=findViewById(R.id.btnRegister); btnRegister.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { registerUser(); } }); // 返回登录按钮监听 Button btnBack=findViewById(R.id.btnBack); btnBack.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent=new Intent(RegisterActivity.this, LoginActivity.class); startActivity(intent); } }); } private void registerUser() { String username=etUsername.getText().toString().trim(); String password=etPassword.getText().toString().trim(); String confirmPassword=etConfirmPassword.getText().toString().trim(); // 验证输入 if (username.isEmpty() || password.isEmpty() || confirmPassword.isEmpty()){ Toast.makeText(this, "所有字段不能为空", Toast.LENGTH_SHORT).show(); return; } if (!password.equals(confirmPassword)){ Toast.makeText(this, "两次输入的密码不一致", Toast.LENGTH_SHORT).show(); return; } // 检查用户名是否已被注册 if (dbHelper.checkUser(username,password)){ Toast.makeText(this, "该用户名已被注册", Toast.LENGTH_SHORT).show(); return; } // 注册新用户 long result=dbHelper.addUser(username,password); if (result > 0){ Toast.makeText(this, "注册成功", Toast.LENGTH_SHORT).show(); Intent intent=new Intent(RegisterActivity.this,LoginActivity.class); startActivity(intent); finish(); }else { Toast.makeText(this, "注册失败", Toast.LENGTH_SHORT).show(); } } private void initView() { etUsername=findViewById(R.id.etUsername); etPassword=findViewById(R.id.etPassword); etConfirmPassword=findViewById(R.id.etConfirmPassword); dbHelper=new DatabaseHelper(this); } }
06-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值