目標:我有一個活動,並在兩個片段之內。理想是傳達這兩個片段,選擇一個類別並更新其項目列表。在活動加載中,類別默認爲結算。Android ListView不顯示/刷新和getView無法正常工作
問題:在活動加載時,ItemsFragment不顯示/更新itemsLisView。此外ItemAdapter的getView方法僅被調用兩次,即使該列表有五個項目。
事實:
- 項目列表被傳遞到適配器
- 設置斷點的代碼,不知道爲什麼之前被正確履行或者如果它很重要,ItemsFragment正在呈現/ CategoriesFragments之前調用。自從CategoriesFragments定位在ItemsFragment之上後,我發現這很奇怪。這就是我寫
if (getArguments() != null)
的原因。在我得到空指針異常之前。
研究:關於這兩個主題都有很多問題。
- Android ListView not refreshing after notifyDataSetChanged with data as Map
- ListFragment Not Rendering and getView() in Adapter Not Being Called
- Android getView() not being called properly?
- BaseAdapter notifyDatasetChanged() called but getView() is never called
這些都是一些鏈接的例子(十萬)我經歷了,試圖找到我的情況的解決方案。不幸的是他們都沒有工作。
我已經有這個問題近5天了,我想我在這裏錯過了一些Android概念。這不是與Java編程有關,或者至少我希望如此。
問題:
- 爲什麼ItemsFragment不上的活動負載顯示項目列表? (這可能會解決更新問題)
- 爲什麼ItemAdapter只調用getView兩次,即使Items List正確地給予他更多的項目?
對於任何進一步需要的信息,請不要介意問。 在此先感謝您的幫助。
編輯 - MCVE:
activity_triple_list:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".controller.activities.Lists">
<include layout="@layout/content_triple_list" />
</android.support.design.widget.CoordinatorLayout>
content_triple_list:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="@+id/listsPager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.PagerTabStrip
android:id="@+id/pager_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:paddingBottom="4dp"
android:paddingTop="4dp" />
</android.support.v4.view.ViewPager>
</LinearLayout>
個
fragment_categories:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/categoriesFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TableLayout
android:id="@+id/categoriesTable"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:stretchColumns="4">
<TableRow
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_marginTop="5dp"
android:gravity="center_horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="0"
android:layout_marginLeft="13dp"
android:layout_marginRight="13dp"
android:orientation="vertical">
<TextView
android:id="@+id/category1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="CATEGORY 1"
android:textAlignment="center"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
</TableRow>
</TableLayout>
</LinearLayout>
fragment_items:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@id/itemsFragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<ListView
android:id="@+id/itemsListView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:divider="@null" />
</LinearLayout>
content_row_choose_item:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/custom_row"
android:orientation="vertical"
android:paddingBottom="5dp"
android:paddingLeft="15dp"
android:paddingTop="5dp">
<TextView
android:id="@+id/itemName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TEST"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
custom_row:
個<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:background="#2fff00">
<item android:drawable="@color/colorPrimary" android:state_pressed="true" /> <!-- pressed -->
</selector>
ApplicationUtils:
public final class ApplicationUtils extends Application {
private static Context context;
public void onCreate() {
super.onCreate();
ApplicationUtils.context = getApplicationContext();
}
public static Context getContext() {
return ApplicationUtils.context;
}
public static String getJavaPackageName() {
return ApplicationUtils.context.getPackageName();
}
public static Resources getAppResources() {
return getContext().getResources();
}
public static String getResouceName(Integer id) {
return getAppResources().getResourceName(id);
}
public static String getResourceString(Integer id) {
return getAppResources().getString(id);
}
public static int getResourceId(String variableName, String resourceName, String packageName) {
try {
return getContext().getResources().getIdentifier(variableName, resourceName, packageName);
} catch (Exception e) {
e.printStackTrace();
return -1;
}
}
}
解釋:
public class Lists extends AppCompatActivity implements CategoriesFragment.OnHeadlineSelectedListener {
private String listName;
public void onItemSelected(String currentCategory) {
ItemsFragment itemsCallBackFragment = (ItemsFragment) getSupportFragmentManager().findFragmentById(R.id.itemsFragment);
if (itemsCallBackFragment != null) {
itemsCallBackFragment.updateArticleView(currentCategory);
} else {
ItemsFragment itemFragment = new ItemsFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.itemsFragment, itemFragment);
transaction.addToBackStack(null);
transaction.commit();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_triple_list);
setListsAdapter();
}
private void setListsAdapter() {
ViewPager tripleListViewPager = (ViewPager) findViewById(R.id.listsPager);
FragmentPagerAdapter tripleListFragmentAdapt = new ListsPagerAdapter(getSupportFragmentManager(), "LIST NAME", ApplicationUtils.getContext());
tripleListViewPager.setAdapter(tripleListFragmentAdapt);
}
}
ListsPagerAdapter:
public class ListsPagerAdapter extends FragmentPagerAdapter {
private static int NUM_TABS = 1;
private String listName;
private Context listsContext;
public ListsPagerAdapter(FragmentManager fm, String newListName, Context listsContext) {
super(fm);
setListName(newListName);
setListsContext(listsContext);
}
// Returns total number of pages
@Override
public int getCount() {
return NUM_TABS;
}
// Returns the fragment to display for that page
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return NewItemPagerFragment.newInstance();
default:
return null;
}
}
// Returns the page title for the top indicator
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return listsContext.getResources().getString(R.string.lists_tab_newItem, getListName());
default:
return "$value";
}
}
public String getListName() {
return listName;
}
public void setListName(String listName) {
this.listName = listName;
}
public Context getListsContext() {
return listsContext;
}
public void setListsContext(Context listsContext) {
this.listsContext = listsContext;
}
}
CategoriesFragment:
public class CategoriesFragment extends Fragment {
private List<Integer> categoryIds = new ArrayList<>();
private String currentCategory;
private View categoriesView;
OnHeadlineSelectedListener itemCallback;
public interface OnHeadlineSelectedListener {
void onItemSelected(String categoryName);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
itemCallback = (OnHeadlineSelectedListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
categoriesView = inflater.inflate(R.layout.fragment_categories, container, false);
categoriesView.setId(R.id.categoriesFragment);
return categoriesView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setCategoriesListener();
setDefaultSelectedCategory();
}
private void setCategoriesListener() {
categoryIds.add(R.id.category1);
for (Integer id : categoryIds) {
setListener(id);
}
}
private void setListener(final int categoryId) {
final ImageView categoryImg = (ImageView) categoriesView.findViewById(categoryId);
categoryImg.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
removePreviousSelectedCategory(categoryImg);
selectCategory(categoryId, categoryImg);
loadItemList();
}
});
}
private void removePreviousSelectedCategory(ImageView categoryImg) {
for (Integer id : categoryIds) {
final ImageView imgView = (ImageView) categoriesView.findViewById(id);
if (imgView.getTag() != null) {
String previousSelectedCategory = (String) imgView.getTag();
if (StringUtils.contains(previousSelectedCategory, Application.SELECTED)) {
previousSelectedCategory = previousSelectedCategory.replace(Application.SELECTED, "");
categoryImg.setTag(previousSelectedCategory);
Integer previousSelectedCategoryId = ApplicationUtils.getResourceId(previousSelectedCategory, Application.RES_DRAWABLE, ApplicationUtils.getJavaPackageName());
imgView.setImageResource(previousSelectedCategoryId);
}
}
}
}
private void selectCategory(int categoryId, ImageView categoryImg) {
String newSelectedCategory = ApplicationUtils.getResouceName(categoryId) + Application.SELECTED;
setCurrentCategory(newSelectedCategory);
newSelectedCategory = newSelectedCategory.replace(Application.META_INFO_ID, "");
categoryImg.setTag(newSelectedCategory);
Integer currentCategoryId = ApplicationUtils.getResourceId(newSelectedCategory, Application.RES_DRAWABLE, ApplicationUtils.getJavaPackageName());
categoryImg.setImageResource(currentCategoryId);
}
public String getCurrentCategory() {
return currentCategory;
}
public void setCurrentCategory(String currentCategory) {
this.currentCategory = currentCategory;
}
private void loadItemList() {
itemCallback.onItemSelected(getCurrentCategory());
}
private void setDefaultSelectedCategory() {
Integer categoryId = R.id.category1;
final ImageView categoryImg = (ImageView) categoriesView.findViewById(categoryId);
selectCategory(categoryId, categoryImg);
loadItemList();
}
}
ItemsFragment:
public class ItemsFragment extends Fragment {
private View itemsFragmentView;
private ListView itemsListView;
private ItemAdapter itemsListAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
itemsFragmentView = inflater.inflate(R.layout.fragment_items, container, false);
itemsListView = (ListView) itemsFragmentView.findViewById(R.id.itemsListView);
setItemsListAdapter();
return itemsFragmentView;
}
public void updateArticleView(String categoryName) {
getSelectedCategoryList();
}
private void getSelectedCategoryList() {
List<String> testList = new ArrayList<>();
testList.add("TEST ITEM");
itemsListAdapter.update(testList);
}
private void setItemsListAdapter() {
itemsListAdapter = new ItemAdapter(getActivity(), R.layout.fragment_items, new ArrayList<String>());
itemsListView.setAdapter(itemsListAdapter);
}
}
ItemAdapter:
public class ItemAdapter extends ArrayAdapter<String> {
private List<String> items = new ArrayList<>();
private LayoutInflater rowInflater;
public ItemAdapter(Context context, int resource, List<String> itemsList) {
super(context, resource, itemsList);
this.items = itemsList;
this.rowInflater = LayoutInflater.from(context);
}
private class ItemHolder {
TextView itemNameView;
}
@Override
public View getView(int position, View rowView, ViewGroup parent) {
ItemHolder itemHolder;
if (rowView == null) {
rowView = rowInflater.inflate(R.layout.content_row_choose_item, parent, false);
itemHolder = new ItemHolder();
itemHolder.itemNameView = (TextView) rowView.findViewById(R.id.itemName);
rowView.setTag(itemHolder);
} else {
itemHolder = (ItemHolder) rowView.getTag();
}
String itemName = getItem(position);
if (StringUtils.isNotEmpty(itemName) && itemHolder.itemNameView != null) {
itemHolder.itemNameView.setText(itemName);
System.out.println("ITEM NAME ### " + itemHolder.itemNameView.getText());
}
return rowView;
}
public void update(List<String> items) {
this.items.clear();
this.items.addAll(items);
this.notifyDataSetChanged();
}
public List<String> getItems() {
return items;
}
}
不要這樣做..'this.items =項目;'。相反,嘗試'this.items.clear(); this.items.addAll(items)' –
@ cricket_007我試過這樣做,但由於ItemList是在Adapter的實例化中引用的,所以如果我清除一次該列表,那麼一切都會消失。 –
@ cricket_007基於你說我帶着想法在'getSelectedCategory'內創建一個本地列表並傳遞給Adapter,仍然不起作用的想法... –