2012-11-18 83 views
3

这里是我的活动代码:ExpandableListView与CursorTreeAdapter抛出IllegalStateException异常

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(); 
    } 
} 

我需要的是在每个标签页中的数据库光标数据的EnxpandableListView一个PagerView。所有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) 

希望有人聪明比我可以帮我找出这个问题......我做了很多试探性没有成功。

+0

定制适配器代码是在中间:MyExpandableListAdapter延伸SimpleCursorTreeAdapter – GPTechinno

+0

我的坏。这种例外情况出现在某些点上的群体儿童“游标”处于“空”状态。如果你打算让组一直开着,也许你会考虑使用一个普通的'ListView',它有两种类型的行,分别是组和子行。 – Luksprog

+0

非常有趣的ListView中的两种类型的行,我会用这种方式挖掘。事实上,我发布了完整的主Activity代码,希望一些高级程序员做出一些评论,比如“你不应该把asynctask放在主要活动中”,因为我是一名初学android应用程序开发人员,我不希望我的代码很好举办... – GPTechinno

回答

1

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); 

和init CursorLoader:

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