【发布时间】:2019-06-18 15:05:45
【问题描述】:
我有一个包含 >100 个对象的数据库。每个对象都有一个特定的图像文件名、主题字符串、标题字符串和 pdf 文件名。
我有一个活动,它是对象的网格视图。
第一次创建网格视图时,会加载要显示的对象数组。数组的确切内容可能因我第一次打开活动时运行的数据库查询而异。
默认设置是检索并显示数据库中的所有对象。但是,我有时只检索和显示对象的子集(基于主题)。
单击网格中的按钮会打开一个显示该对象 pdf 的活动。很好。
问题是,当我从 PDF 活动“返回”时,会重新创建网格视图。始终使用“默认”所有对象。
因此,如果我有一个仅显示某个“主题”对象的网格视图,如果我随后打开 pdf 活动,则在返回时重新创建网格视图并显示所有对象,而不是 pdf 活动之前的原始网格视图开始了。
问题: 1) 如何在不重新创建网格视图的情况下返回网格视图?
代码:
public class SubjectListActivity extends AppCompatActivity {
String DB_NAME = "XXXXX.sqlite";
String TABLE_NAME = "XXXXX";
DataBaseHelper myDBHelper;
private GridView gridView;
private MyAdapter myAdapter;
private ArrayList<Subject> subjectsArrayList;
private Context context;
private String subjectAreas = ""; // this is sent to the activity from whichever activity opened it.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_subject_list);
Bundle extras = getIntent().getExtras();
if (extras != null) {
subjectAreas = extras.getString("subjectAreas");
}
gridView = findViewById(R.id.gv);
// Database
AssetDatabaseOpenHelper assetDatabaseOpenHelper = new AssetDatabaseOpenHelper(this, DB_NAME);
assetDatabaseOpenHelper.saveDatabase();
myDBHelper = new DataBaseHelper(this, DB_NAME);
// populates subjectsArray
subjectsArrayList = populateSubjects();
loadGrid();
// listener
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String title = subjectsArrayList.get(position).getSubjectTitle();
String iconStyle = subjectsArrayList.get(position).getSubjectIconStyle();
String pdf = subjectsArrayList.get(position).getSubjectPDF();
String ref = subjectsArrayList.get(position).getSubjectRefs();
String linked = subjectsArrayList.get(position).getSubjectLinked();
Intent intent = new Intent(view.getContext(), SubjectActivity.class);
intent.putExtra("title", title);
intent.putExtra("icon", iconStyle);
intent.putExtra("pdf", pdf);
intent.putExtra("ref", ref);
intent.putExtra("linked", linked);
intent.putExtra("subjectAreas", subjectAreas);
startActivityForResult(intent, 1);
}
});
}
private void loadGrid(){
myAdapter = new MyAdapter(getApplicationContext(), subjectsArrayList);
gridView.setAdapter(myAdapter);
}
// The SQL query that populates the subjectArray depends on the 'subjectAreas' string which is set when the activity first opens. The default is 'getAllSubjects'
private ArrayList<Subject> populateSubjects() {
Cursor res = myDBHelper.getAllSubjects(TABLE_NAME);
if (subjectAreas.equals("emerg")){res = myDBHelper.getEmergSubjects(TABLE_NAME);}
else if (subjectAreas.equals("all")){res = myDBHelper.getAllSubjects(TABLE_NAME);}
else if (subjectAreas.equals("ax")){res = myDBHelper.getAxSubjects(TABLE_NAME);}
else if (subjectAreas.equals("mx")){res = myDBHelper.getMxSubjects(TABLE_NAME);}
else if (subjectAreas.equals("ref")){res = myDBHelper.getRefSubjects(TABLE_NAME);}
else if (subjectAreas.equals("cal")){res = myDBHelper.getCalSubjects(TABLE_NAME);}
else if (subjectAreas.equals("search")){res = myDBHelper.getSearchSubjects(TABLE_NAME, keywords);}
ArrayList<Subject> list = new ArrayList<>();
if (res.getCount() == 0) {
} else {
while (res.moveToNext()) {
Subject subject = new Subject();
subject.setSubjectID(res.getString(0));
subject.setSubjectTitle(res.getString(1));
subject.setSubjectIconStyle(res.getString(2));
subject.setSubjectPDF(res.getString(3));
subject.setSubjectKeywords(res.getString(4));
subject.setSubjectLinked(res.getString(5));
subject.setSubjectRefs(res.getString(6));
list.add(subject);
}
}
return list;
}
// Tried sending 'back' subjectAreas from PDF activity and re-populating the array and gridview - this doesn't seem to be called
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1) {
if(resultCode == RESULT_OK) {
subjectAreas = data.getStringExtra("subjectAreas");
subjectsArrayList = populateSubjects();
myAdapter = new MyAdapter(getApplicationContext(), subjectsArrayList);
gridView.invalidateViews();
gridView.setAdapter(myAdapter);
}
}
}
}
提前致谢
更新: 使用 savedInstanceState 来“保存”我的 subjectAreas 字符串,我使用了以下内容:
private String subjectAreas = "";
private static final String subjectAreasSaved = "";
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_subject_list);
Bundle extras = getIntent().getExtras();
if (extras != null) {
subjectAreas = extras.getString("subjectAreas");
title = extras.getString("title");
keywords = extras.getStringArrayList("keywords");
}
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
subjectAreas = savedInstanceState.getString(subjectAreasSaved);
}
还有:
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putString(subjectAreasSaved, subjectAreas);
super.onSaveInstanceState(savedInstanceState);
}
当第二个活动是开放式的时是否会自动调用 onSaveINstanceState 还是我需要调用它?目前似乎没有任何事情发生
【问题讨论】:
-
我建议您编辑您的问题并提供此活动的minimal reproducible example,显示它何时以及如何设置网格,以及它如何启动 PDF 查看活动。与活动输出的屏幕截图相比,该代码对于获得答案的价值要高得多。
-
完成,感谢任何帮助,进一步的建议
-
如果这是完整的活动类,我不明白为什么它会纯粹基于前进/后退导航重新创建。您是否在设置的开发人员选项中启用了“不保留活动”?但是,您将遇到配置更改问题,这就是
onSaveInstanceState()或ViewModel发挥作用的地方。顺便说一句,FWIW,您在这里使用的方法(例如,GridView,活动中的数据库 I/O)有点旧。 -
尚未启用“不保留活动”,因为所有测试都在模拟器上(目前实际上没有安卓设备(!))。猜猜潜在的“用户”可以启用此功能,所以我需要为该结果编写代码?看来“onSaveInstanceState”是我需要的(同意?)。感谢您的建议:gridview,因为我相信您可以猜到我不是 android 开发人员,只是试图重新创建我的 iOS 应用程序(由于各种原因使用 sqlite)。这些是第一次尝试进入 android 并希望运行“基本版本”,并且一旦舒服就会考虑其他方法。谢谢
-
“我需要为这个结果编码吗?” ——我不会担心的。 “看来,'onSaveInstanceState' 是我需要的(同意?)” - 您需要为配置更改做一些事情,但您对症状的描述不包括配置更改。关于您问题中的问题,请在您的
onCreate()方法中的某处放置一个断点,并查看当您在查看 PDF 后返回此活动时是否会触发该断点。如果没有,那么该活动没有被重新创建,并且正在发生其他事情。
标签: android gridview oncreate resume