【发布时间】:2023-03-10 20:06:01
【问题描述】:
首先,如果我的思想不正确,请纠正我,这是我第一次使用 Fragment 并且不擅长 ListView 适配器。
我目前正在使用DrawerLayout,它由您所期望的片段组成,我有一个FAB,单击它会在SQLite db 条目中添加一个新条目,并刷新ListView(从数据库中提取的数据)。
我的想法是我可以在 ActivityMain 中获取 ListView 适配器(在 Profiles 片段类中)(因为 FAB 不是片段的一部分,并且根据当前片段将有不同的操作),然后调用 .notifyDataSetChanged( )
Profiles 片段类
public class Profiles extends Fragment{
public ProfileListAdapter adapter;
(...)
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DBHandler db = new DBHandler(getActivity().getBaseContext());
adapter = new ProfileListAdapter(getActivity().getBaseContext(), db.getAllProfiles());
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
ListView profileListView = (ListView)view.findViewById(R.id.profileListView);
profileListView.setAdapter(adapter);
}
ProfilesListAdapter(来自here)
public class ProfileListAdapter extends ArrayAdapter<Profile> {
private static class ViewHolder {
TextView name;
}
public ProfileListAdapter(Context context, ArrayList<Profile> profileList) {
super(context, R.layout.profile_row, profileList);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
Profile profile = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
ViewHolder viewHolder; // view lookup cache stored in tag
if (convertView == null) {
// If there's no view to re-use, inflate a brand new view for row
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.profile_row, parent, false);
viewHolder.name = (TextView) convertView.findViewById(R.id.profileListRowValue);
// Cache the viewHolder object inside the fresh view
convertView.setTag(viewHolder);
} else {
// View is being recycled, retrieve the viewHolder object from tag
viewHolder = (ViewHolder) convertView.getTag();
}
// Populate the data into the template view using the data object
viewHolder.name.setText(profile.name);
// Return the completed view to render on screen
return convertView;
}
}
在 DBHelper 类中
// Getting All Profiles
public ArrayList<Profile> getAllProfiles() {
ArrayList<Profile> profileListItems = new ArrayList<Profile>();
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_PROFILE;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, new String[] {});
// looping through all rows and adding to list
if (cursor.moveToLast()) {
do {
Profile profile = new Profile();
profile.setId(Integer.parseInt(cursor.getString(0)));
profile.setName(cursor.getString(1));
// Adding contact to list
profileListItems.add(profile);
} while (cursor.moveToPrevious());
}
// return contact list
cursor.close();
return profileListItems;
}
这就是我在 MainActivity 中控制 FAB 点击时尝试做的事情,幻数只是一个 int,它从 0 开始并递增 1,以便我更轻松地测试 db / ListView。
db.addProfile(new Profile("Test Profile " + magicNumber));
magicNumber++;
FragmentManager fm = getSupportFragmentManager();
Profiles fragment = (Profiles) fm.findFragmentById(R.id.fragmentProfiles);
//I gave the fragment xml main FrameLayout an ID
fragment.updateListView();
片段类内部
public void updateListView(){
adapter.notifyDataSetChanged();
}
我还尝试从 Profiles 片段类中返回适配器,我认为这是解决此问题的错误方法。
public ProfileListAdapter getAdapter(){
return adapter;
}
我总是以
java.lang.NullPointerException: Attempt to invoke virtual method 'void layout.Profiles.updateListView()' on a null object reference
或
java.lang.NullPointerException: Attempt to invoke virtual method 'com.xxxxx.xxxxx.appName.ProfileListAdapter layout.Profiles.getAdapter()' on a null object reference
在我看来,似乎无法从片段 Profiles 类外部访问适配器,不确定是否是这样 - 即使不确定如何解决这个问题。让我知道是否需要任何其他代码/logcat。谢谢!
【问题讨论】:
-
如果你想让一个FAB动作依赖于fragment,那为什么不能在每个fragment布局中添加一个FAB呢?
-
@CodeCody 老实说,我没有想到这一点,因为 FAB 已自动添加到 ActivityMain 并且在所有片段上都可见。我使用 switch 语句来区分正在使用的片段并相应地设置 onClick 操作。如果将 FAB 添加到每个片段是更好的方法,我会试一试!
标签: android listview android-fragments android-arrayadapter