进度条一直显示不消失

在程序中使用进度条,但是出现这个情况:进度条一直显示很久很久都不消失。在程序中使用显示和隐藏进度条的代码片段如下所示

public void showProgressDialog(String msg) {    if(progressDialog != null && progressDialog.isShowing()) {        progressDialog.dismiss();        progressDialog = null;    }    progressDialog = ProgressDialog.show(context, "", msg);}public void hideProgressDialog() {    if(progressDialog != null && progressDialog.isShowing()) {        progressDialog.dismiss();        progressDialog = null;    }}

在程序中调用以上方法的代码片段是

@Overridepublic void onRequestStarted(int requestCode) {    switch(requestCode) {    case REQUEST_GET_TJ:        showProgressDialog("正在加载数据,请稍等...");        break;    }}@Overridepublic void onRequestFinished(int requestCode, int resultCode, IVideoResult result) {    switch(requestCode) {    case REQUEST_GET_TJ:        hideProgressDialog();        processGetTJ(resultCode, result);    break;    }}

在Fragment嵌套Fragment时出现以下错误

Binary XML file line #49: Duplicate id 0x7f070071, tag null, or parent id 0x0 with another fragment for com.tvie.ivideo.pad.main.HotVideoFragment

11-18 11:33:45.851: E/AndroidRuntime(8376): android.view.InflateException: Binary XML file line #49: Error inflating class fragment11-18 11:33:45.851: E/AndroidRuntime(8376): Caused by: java.lang.IllegalArgumentException: Binary XML file line #49: Duplicate id 0x7f070071, tag null, or parent id 0x0 with another fragment for com.tvie.ivideo.pad.main.HotVideoFragment11-18 11:33:45.851: E/AndroidRuntime(8376):     at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:285)11-18 11:33:45.851: E/AndroidRuntime(8376):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:685)11-18 11:33:45.851: E/AndroidRuntime(8376):     ... 23 more

嵌套的Fragment布局如下所示(fragment_main.xml)

Fragment嵌套和销毁问题

1、不要直接将Fragement写在XML文件里,这样会导致Fragment对象无法销毁,产生内存溢出。在代码动态的new 和add Fragement才是正确的做法。

2、使用抽屉方法,在XML文件里放两个LinearLayout,然后在代码中将Fragment加进这两个LinearLayout中。

要移动Fragment,就是移动LinearLayout,可以通过修改margin值来达到渐变移动的效果。

记得当Fragment移除屏幕的时候,detach掉它。

动态添加Fragment

参考1:初识Fragmentの动态添加

参考2:Dynamically add fragment into fragment

企图调用LinearLayout的addView方法添加Fragment(如下所示)

经过验证这个方法不可行

private void initializeFragments() {    Logger.v(TAG, "@initializeFragments.");    recmdFragment = new RecommandFragment();    hotFragment = new HotVideoFragment();    channelFragment = new MyChannelFragment();    linearLayout1.addView(recmdFragment.getView(),            new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));    linearLayout2.addView(hotFragment.getView(),            new LayoutParams(linearLayout1.getMeasuredWidth() * 2 / 3, LayoutParams.MATCH_PARENT));    linearLayout2.addView(channelFragment.getView(),            new LayoutParams(linearLayout1.getMeasuredWidth() * 1 / 3, LayoutParams.MATCH_PARENT));}

参考stackoverflow网站上的资料,得到正确添加Fragment的方法

private void initializeFragments() {    Logger.v(TAG, "@initializeFragments.");    hotFragment = new HotVideoFragment();    channelFragment = new MyChannelFragment();    recmdFragment = new RecommandFragment();    FragmentTransaction trac = getFragmentManager().beginTransaction();    trac.add(R.id.hot_video_fragment, hotFragment);    trac.add(R.id.my_channel_fragment, channelFragment);    trac.add(R.id.recommand_fragment, recmdFragment);    trac.commit();}

再看下布局文件也被重新定义,将原来Fragment标记全部改为LinearLayout

是在onCreateView方法调用initializeFragment的吗?NO,是在onLayoutChange方法中调用

private void initializeView() {                                                                                                                                                                                                                                                                                                                                                                                                                                                  linearLayout1.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {                                                                                                                                                                                                                                                                                                                                                                                                                                                          @Override        public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight,                int oldBottom) {            initializeFragments();            linearLayout1.removeOnLayoutChangeListener(this);        }    });}

变量context竟然null值

先看打印出来的日志

11-18 13:44:49.531: V/MainFragment(21389): @onCreateView11-18 13:44:49.541: V/MainFragment(21389): @initializeView. create each fragment.11-18 13:44:49.541: V/MainFragment(21389): @onActivityCreated. data isn't null. data.size >> 511-18 13:44:49.541: V/HotVideoFragment(21389): @createHotImageView. context >> null

从日志来看:第二次启动推荐首页,先后要执行MainFragment的onCreateView方法,onActivityCreated方法,但是没有执行HotVideoFragment的onCreateView方法,onActivityCreated方法

新建Fragment会调用onCreate方法

嵌套在Fragment中的子Fragment。每次创建XXXFragment对象时,都会去调用onCreate方法。至少要等XXXFragment的onCreate等方法执行完(即创建完成)再去操作XXXFragment的界面元素才不出问题。

以下日志显示程序运行正常,没有出现context空指针问题

11-18 14:31:36.261: V/MainFragment(25136): @onCreateView11-18 14:31:36.271: V/MainFragment(25136): @initializeView. create each fragment.11-18 14:31:36.271: V/MainFragment(25136): @onActivityCreated. data isn't null. data.size >> 511-18 14:31:36.271: V/MainFragment(25136): @onActivityCreated. ready >> false11-18 14:31:36.271: V/MainFragment(25136): @onLayoutChange11-18 14:31:36.271: V/MainFragment(25136): @initializeFragments. add fragments to parent.11-18 14:31:36.281: V/RecommandFragment(25136): @onCreate11-18 14:31:36.281: V/RecommandFragment(25136): @onCreateView11-18 14:31:36.291: V/HotVideoFragment(25136): @onCreate11-18 14:31:36.291: V/HotVideoFragment(25136): @onCreateView11-18 14:31:36.341: V/MainFragment(25136): @onActivityCreated. after 73 ms, ready >> true11-18 14:31:36.351: V/MainFragment(25136): @renderInFragments

程序中的代码片段,在onActivityCreated方法中创建线程进入等待状态

final long start = System.currentTimeMillis();new Thread() {    public void run() {        while(!isReady() || !recmdFragment.isReady() || !hotFragment.isReady()) {            try {                Thread.sleep(1);            } catch (InterruptedException e) { }        }        long end = System.currentTimeMillis();        Logger.v(TAG, "@onActivityCreated. after " + (end - start) + " ms, ready >> " + isReady());        handler.sendEmptyMessage(1);    }}.start();

其中新建XXXFragment的onCreate方法的调用执行只跟FragmentTransaction.add方法有关系。纯粹调用XXXFragment的构造方法不会去调用执行onCreate方法,可是执行FragmentTransaction.add方法之后就不同,XXXFragment的onCreate方法就被调用。同样,当调用FragmentTransaction.remove方法之后,XXXFragment的onDestroy方法也会被调用。当然,在调用FragmentTransaction的add或remove方法之后必须调用FragmentTransaction的commit方法。

先看下打印出来的日志

11-18 15:12:53.971: V/MainFragment(29470): @onCreateView11-18 15:12:53.971: V/MainFragment(29470): @initializeView. create each fragment.11-18 15:12:53.971: V/MainFragment(29470): @initializeFragments. add fragments by FragmentTransaction.11-18 15:12:53.971: V/MainFragment(29470): @onActivityCreated. data isn't null. data.size >> 511-18 15:12:53.971: V/MainFragment(29470): @onActivityCreated. ready >> false11-18 15:12:53.971: V/RecommandFragment(29470): @onCreate11-18 15:12:53.971: V/RecommandFragment(29470): @onCreateView11-18 15:12:53.981: V/HotVideoFragment(29470): @onCreate11-18 15:12:53.981: V/HotVideoFragment(29470): @onCreateView11-18 15:12:54.011: V/MainFragment(29470): @onActivityCreated. after 41 ms, ready >> false11-18 15:12:54.011: V/MainFragment(29470): @onLayoutChange11-18 15:12:54.021: V/MainFragment(29470): @renderInFragments...11-18 15:13:37.021: V/MainFragment(29470): @onDestroyView. remove fragments. by FragmentTransaction.11-18 15:13:37.031: V/HotVideoFragment(29470): @onDestroyView11-18 15:13:37.031: V/HotVideoFragment(29470): @onDestroy11-18 15:13:37.031: V/RecommandFragment(29470): @onDestroyView11-18 15:13:37.031: V/RecommandFragment(29470): @onDestroy

再看下调用FragmentTransaction的add和remove方法的代码片段

private void initializeFragments() {    Logger.v(TAG, "@initializeFragments. add fragments by FragmentTransaction.");    FragmentTransaction trac = getFragmentManager().beginTransaction();    trac.add(R.id.hot_video_fragment, hotFragment);    trac.add(R.id.my_channel_fragment, channelFragment);    trac.add(R.id.recommand_fragment, recmdFragment);    trac.commit();}@Overridepublic void onDestroyView() {    Logger.v(TAG, "@onDestroyView. remove fragments. by FragmentTransaction.");    super.onDestroyView();    FragmentTransaction trac = getFragmentManager().beginTransaction();    trac.remove(hotFragment);    trac.remove(channelFragment);    trac.remove(recmdFragment);    trac.commit();    hotFragment = null;    channelFragment = null;    recmdFragment = null;    linearLayout1 = null;}