android - 带有 CursorTreeAdapter 的 ExpandableListView 抛出 IllegalStateException

标签 android

这是我的 Activity 代码:

public class MenuActivity extends FragmentActivity implements
    ActionBar.TabListener {

/**
 * The {@link android.support.v4.view.PagerAdapter} that will provide
 * fragments for each of the sections. We use a
 * {@link android.support.v4.app.FragmentPagerAdapter} derivative, which
 * will keep every loaded fragment in memory. If this becomes too memory
 * intensive, it may be best to switch to a
 * {@link android.support.v4.app.FragmentStatePagerAdapter}.
 */
SectionsPagerAdapter mSectionsPagerAdapter;

/**
 * The {@link ViewPager} that will host the section contents.
 */
ViewPager mViewPager;

static DatabaseManager db;

// url to make request
private static String URL = "http://192.168.88.111/MenuManager/mm_menu.php";

static long currLangId;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.menu);

    final String DB_NAME = "menu"; // the name of our database
    final String DB_PATH = "/data/data/com.mypackage.menu/databases/";

    File dbFile = new File(DB_PATH + DB_NAME);
    Boolean firstLaunch = !dbFile.exists();

    db = new DatabaseManager(this);

    // new RetreiveJSONAndCacheSQLiteMenu().execute(URL);
    if (firstLaunch) {
        InputStream is = getResources().openRawResource(R.raw.menu);
        Writer writer = new StringWriter();
        char[] buffer = new char[1024];
        try {
            Reader reader = new BufferedReader(new InputStreamReader(is,
                    "UTF-8"));
            int n;
            while ((n = reader.read(buffer)) != -1) {
                writer.write(buffer, 0, n);
            }
            is.close();
            JSONObject jObj = new JSONObject(writer.toString());
            parseMenuJSON(jObj);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    currLangId = db.getLangIdFromName(db.LANG_ENGLISH);

    // Create the adapter that will return a fragment for each
    // primary sections of the app.
    mSectionsPagerAdapter = new SectionsPagerAdapter(
            getSupportFragmentManager());

    // Set up the action bar.
    final ActionBar actionBar = getActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) findViewById(R.id.pager);
    mViewPager.setAdapter(mSectionsPagerAdapter);
    // try to hide Navigation bar
    // mViewPager.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);

    // When swiping between different sections, select the corresponding
    // tab.
    // We can also use ActionBar.Tab#select() to do this if we have a
    // reference to the Tab.
    mViewPager
            .setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
                @Override
                public void onPageSelected(int position) {
                    actionBar.setSelectedNavigationItem(position);
                }
            });

    for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
        actionBar.addTab(actionBar.newTab()
                .setText(mSectionsPagerAdapter.getPageTitle(i))
                .setTabListener(MenuActivity.this));
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    return db.createMenuFromLangs(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    currLangId = db.getLangIdFromName(item.getTitle());
    ActionBar actionBar = getActionBar();
    actionBar.removeAllTabs();
    for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
        actionBar.addTab(actionBar.newTab()
                .setText(mSectionsPagerAdapter.getPageTitle(i))
                .setTabListener(MenuActivity.this));
    }
    /*
     * for (int i = 0; i <
     * listView.getExpandableListAdapter().getGroupCount(); i++)
     * listView.expandGroup(i);
     */
    return true;
}

public void onTabUnselected(ActionBar.Tab tab,
        FragmentTransaction fragmentTransaction) {
}

public void onTabSelected(ActionBar.Tab tab,
        FragmentTransaction fragmentTransaction) {
    // When the given tab is selected, switch to the corresponding page in
    // the ViewPager.
    mViewPager.setCurrentItem(tab.getPosition());
}

public void onTabReselected(ActionBar.Tab tab,
        FragmentTransaction fragmentTransaction) {
}

/**
 * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
 * one of the primary sections of the app.
 */
public class SectionsPagerAdapter extends FragmentPagerAdapter {

    public SectionsPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int i) {
        Fragment fragment = new MenuCategFragment();
        Bundle args = new Bundle();
        args.putInt(MenuCategFragment.ARG_SECTION_NUMBER, i);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public int getCount() {
        return db.getNumberPages(currLangId);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return db.getPageName(position, currLangId);
    }
}

public class MyExpandableListAdapter extends SimpleCursorTreeAdapter {
    public MyExpandableListAdapter(Cursor cursor, Context context,
            int groupLayout, String[] groupFrom, int[] groupTo,
            int childLayout, String[] childFrom, int[] childTo) {
        super(context, cursor, groupLayout, groupFrom, groupTo,
                childLayout, childFrom, childTo);
    }

    @Override
    protected Cursor getChildrenCursor(Cursor groupCursor) {
        return db.getAllItemsInCateg(groupCursor.getLong(0));
    }
}

public class MenuCategFragment extends Fragment {
    public MenuCategFragment() {
    }

    public static final String ARG_SECTION_NUMBER = "section_number";

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        final ExpandableListView listView = new ExpandableListView(
                getActivity());
        listView.setId(android.R.id.list);
        Bundle args = getArguments();

        Cursor cursor = db.getAllCategsInPage(
                args.getInt(ARG_SECTION_NUMBER), currLangId);

        String[] fromCategColumns = { db.CATEG_NAME };
        int[] toCategViews = { R.id.categName };
        String[] fromItemColumns = { db.ITEM_NAME, db.ITEM_DESC,
                db.ITEM_PRICE };
        int[] toItemViews = { R.id.itemName, R.id.itemDesc, R.id.itemPrice };

        ExpandableListAdapter adapter = new MyExpandableListAdapter(cursor,
                getActivity(), R.layout.categ, fromCategColumns,
                toCategViews, R.layout.item, fromItemColumns, toItemViews);
        listView.setAdapter(adapter);
        for (int i = 0; i < adapter.getGroupCount(); i++)
            listView.expandGroup(i);
        /*
         * listView.setOnGroupClickListener(new
         * ExpandableListView.OnGroupClickListener() { public boolean
         * onGroupClick(ExpandableListView arg0, View itemView, int
         * itemPosition, long itemId) { arg0.expandGroup(itemPosition);
         * return true; } });
         */
        listView.setOnGroupCollapseListener(new ExpandableListView.OnGroupCollapseListener() {
            public void onGroupCollapse(int groupPosition) {
                listView.expandGroup(groupPosition);
            }
        });
        return listView;
    }
}

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    try {
        if (!hasFocus) {
            Object service = getSystemService("statusbar");
            Class<?> statusbarManager = Class
                    .forName("android.app.StatusBarManager");
            Method collapse = statusbarManager.getMethod("collapse");
            collapse.setAccessible(true);
            collapse.invoke(service);
        }
    } catch (Exception ex) {
    }
}

public class RetreiveJSONAndCacheSQLiteMenu extends
        AsyncTask<String, Void, JSONObject> {
    InputStream is = null;
    JSONObject jObj = null;
    String json = "";

    protected JSONObject doInBackground(String... urls) {

        // Making HTTP request
        try {
            // defaultHttpClient
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpPost httpPost = new HttpPost(urls[0]);

            HttpResponse httpResponse = httpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();
            is = httpEntity.getContent();

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(is, "iso-8859-1"), 8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
            is.close();
            json = sb.toString();
        } catch (Exception e) {
            Log.e("Buffer Error", "Error converting result " + e.toString());
        }

        // try parse the string to a JSON object
        try {
            jObj = new JSONObject(json);
        } catch (JSONException e) {
            Log.e("JSON Parser", "Error parsing data " + e.toString());
        }
        return jObj;
    }

    protected void onPostExecute(JSONObject json) {
        parseMenuJSON(json);
    }
}

public void parseMenuJSON(JSONObject json) {
    // JSON Node names
    final String TAG_LANGS = "langs";
    final String TAG_PAGES = "pages";
    final String TAG_CATEGORIES = "categories";
    final String TAG_ITEMS = "items";
    // final String TAG_ID = "id";
    final String TAG_NAME = "name";
    final String TAG_DESC = "desc";
    final String TAG_PRICE = "price";
    // final String TAG_PHOTO = "photo";

    // JSONArray
    JSONArray langs = null;
    JSONArray pages = null;
    JSONArray categories = null;
    JSONArray items = null;

    try {
        db.voidDatabase();
        langs = json.getJSONArray(TAG_LANGS);
        long currLangId = 0;
        for (int h = 0; h < langs.length(); h++) {
            JSONObject lang = langs.getJSONObject(h);
            currLangId = db.addLang(lang.getString(TAG_NAME));
            pages = lang.getJSONArray(TAG_PAGES);
            long currPageId = 0;
            for (int i = 0; i < pages.length(); i++) {
                JSONObject page = pages.getJSONObject(i);
                currPageId = db.addPage(page.getString(TAG_NAME),
                        currLangId);
                categories = page.getJSONArray(TAG_CATEGORIES);
                long currCategId = 0;
                for (int j = 0; j < categories.length(); j++) {
                    JSONObject categorie = categories.getJSONObject(j);
                    currCategId = db.addCateg(
                            categorie.getString(TAG_NAME), currPageId);
                    items = categorie.getJSONArray(TAG_ITEMS);
                    for (int k = 0; k < items.length(); k++) {
                        JSONObject item = items.getJSONObject(k);
                        db.addItem(item.getString(TAG_NAME),
                                item.getString(TAG_DESC),
                                item.getInt(TAG_PRICE), currCategId);
                    }
                }
            }
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

我需要的是一个 PagerView,在每个选项卡中都有一个 EnxpandableListView,其中包含来自数据库 Cursor 的数据。所有 ExpandableListView 都应始终处于展开状态。它应该支持多语言(来自 ActionBar 中的菜单按钮)。

它几乎可以工作,但我有奇怪的 FC :

W/dalvikvm(13556): threadid=1: thread exiting with uncaught exception (group=0x40a641f8)
E/AndroidRuntime(13556): FATAL EXCEPTION: main
E/AndroidRuntime(13556): java.lang.IllegalStateException: this should only be called when the cursor is valid
E/AndroidRuntime(13556): at android.widget.CursorTreeAdapter.getGroupView(CursorTreeAdapter.java:198)
E/AndroidRuntime(13556): at android.widget.ExpandableListConnector.getView(ExpandableListConnector.java:445)
E/AndroidRuntime(13556): at android.widget.AbsListView.obtainView(AbsListView.java:2012)
E/AndroidRuntime(13556): at android.widget.ListView.makeAndAddView(ListView.java:1772)
E/AndroidRuntime(13556): at android.widget.ListView.fillDown(ListView.java:672)
E/AndroidRuntime(13556): at android.widget.ListView.fillSpecific(ListView.java:1330)
E/AndroidRuntime(13556): at android.widget.ListView.layoutChildren(ListView.java:1603)
E/AndroidRuntime(13556): at android.widget.AbsListView.onLayout(AbsListView.java:1863)
E/AndroidRuntime(13556): at android.view.View.layout(View.java:11282)
E/AndroidRuntime(13556): at android.view.ViewGroup.layout(ViewGroup.java:4224)
E/AndroidRuntime(13556): at android.widget.FrameLayout.onLayout(FrameLayout.java:431)
E/AndroidRuntime(13556): at android.view.View.layout(View.java:11282)
E/AndroidRuntime(13556): at android.view.ViewGroup.layout(ViewGroup.java:4224)
E/AndroidRuntime(13556): at android.support.v4.view.ViewPager.onLayout(ViewPager.java:1388)
E/AndroidRuntime(13556): at android.view.View.layout(View.java:11282)
E/AndroidRuntime(13556): at android.view.ViewGroup.layout(ViewGroup.java:4224)
E/AndroidRuntime(13556): at android.widget.FrameLayout.onLayout(FrameLayout.java:431)
E/AndroidRuntime(13556): at android.view.View.layout(View.java:11282)
E/AndroidRuntime(13556): at android.view.ViewGroup.layout(ViewGroup.java:4224)
E/AndroidRuntime(13556): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1628)
E/AndroidRuntime(13556): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1486)
E/AndroidRuntime(13556): at android.widget.LinearLayout.onLayout(LinearLayout.java:1399)
E/AndroidRuntime(13556): at android.view.View.layout(View.java:11282)
E/AndroidRuntime(13556): at android.view.ViewGroup.layout(ViewGroup.java:4224)
E/AndroidRuntime(13556): at android.widget.FrameLayout.onLayout(FrameLayout.java:431)
E/AndroidRuntime(13556): at android.view.View.layout(View.java:11282)
E/AndroidRuntime(13556): at android.view.ViewGroup.layout(ViewGroup.java:4224)
E/AndroidRuntime(13556): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1514)
E/AndroidRuntime(13556): at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2467)
E/AndroidRuntime(13556): at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(13556): at android.os.Looper.loop(Looper.java:137)
E/AndroidRuntime(13556): at android.app.ActivityThread.main(ActivityThread.java:4581)
E/AndroidRuntime(13556): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(13556): at java.lang.reflect.Method.invoke(Method.java:511)
E/AndroidRuntime(13556): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
E/AndroidRuntime(13556): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
E/AndroidRuntime(13556): at dalvik.system.NativeStart.main(Native Method)

希望比我聪明的人可以帮助我发现问题......我做了很多尝试都没有成功。

最佳答案

CursorLoader 解决了这个问题。 简单示例:

public class MenuCategFragment extends Fragment implements LoaderCallbacks<Cursor>

添加 3 个方法和 MyCursorLoaderClass。

@Override
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
    return new MyCursorLoader(getActivity(), db, sectionNumber, currLangId);
}


@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    adapter.setGroupCursor(cursor);
}



@Override
public void onLoaderReset(Loader<Cursor> arg0) {
    // TODO Auto-generated method stub

}

static class MyCursorLoader extends CursorLoader{
    DataBase db;
    int sectionNumber;
    long currLangId;

    public MyCursorLoader(Context context, DataBase db, int sectionNumber, long currLangId) {
       super(context);
       this.db = db;
       this.sectionNumber = sectionNumber;
       this.currLangId = currLangId;
    }

    @Override
       public Cursor loadInBackground() {
          return db.getAllCategsInPage(sectionNumber, currLangId);
       }            

    }

在那之后改变这个:

ExpandableListAdapter adapter = new MyExpandableListAdapter(**null**, getActivity(),    R.layout.categ, fromCategColumns,
            toCategViews, R.layout.item, fromItemColumns, toItemViews);

并初始化 CursorLoader:

getActivity().getSupportLoaderManager().initLoader(0, null, this);

关于android - 带有 CursorTreeAdapter 的 ExpandableListView 抛出 IllegalStateException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13437185/

相关文章:

android - 如何检查当前是否显示启动器/主屏幕

android - Android即时运行总是失败

android - 像描述中那样的应用

android - 如何在 android 中通过电子邮件 Intent 从 sd 卡发送 .apk 文件?

android - 通过 Exchange 服务器从 Android 应用程序自动发送电子邮件

Java/安卓。 int = 文本?

java - 访问非 Activity 类别中的多个传感器

android - 如何使用具有相对布局的 ScrollView

android - "ANR"是异常还是错误还是什么?

Android - 将 RC4 与密码一起使用