片段的UI未显示

时间:2014-04-21 22:31:23

标签: android android-fragments

我试图从我的活动中调用一个片段。正在调用onCreate和onCreateView方法。但是,未显示片段的UI。我也没有在logcat中看到任何错误。

基本上这就是我想要做的。单击activity.xml中的imagebutton后,我调用fetchNotifications()方法,该方法又调用asynctask来做一些工作,然后调用我的片段。在我的片段中,我创建了一个包含多个textview的动态列表视图。

以下是我的代码:

activity_home_screen.xml(我的活动布局):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageButton
        android:id="@+id/imageButton1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="46dp"
        android:src="@drawable/read_msg"
        android:onClick="fetchNotifications"/>

</RelativeLayout>

HomeScreen.java(我的活动类):

public class HomeScreen extends FragmentActivity{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home_screen);
    }

    //Method called from button onClick
    public void fetchNotifications(View view){
        new FetchNotifications().execute("http://x.x.x.x:9000/Android/homescreen/ruby");        
    }

    private class GetNotifications extends AsyncTask<String, String, String>{//some code here}

    private class FetchNotifications extends AsyncTask<String, String, String>{

        FragmentManager fm;

        @Override
        protected String doInBackground(String... params) {
            try {
                URL notifications = new URL(params[0]);
                //JSONObject notificationsJSON = new JSONObject(getResponse(notifications).toString());
                JSONObject notificationsJSON = new JSONObject(globals.JSONS.NOTIFICATIONS);

                if(notificationsJSON!=null){
                    Globals globals = Globals.getInstance();
                    globals.setReplyString(notificationsJSON.getJSONArray("notification").toString());
                    FragmentManager fm = getSupportFragmentManager();
                    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                    ft.add(new DisplayNotifications(), "Notification");
                    ft.commit();
                }
            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null;
        }
    }

    public StringBuilder getResponse(URL url){//some code here}


}

activity_display_notifications.xml(my fragment_layout):

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.buildingcustomadapter.MainActivity"
    tools:ignore="MergeRootFrame">

    <ListView
        android:id="@+id/notifications_listView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>

</FrameLayout>

single_notification.xml(包含将添加到列表视图的textview):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/notification_TextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:text="Small Text"
        android:textAppearance="?android:attr/textAppearanceSmall" />

</RelativeLayout>

最后我的片段类(DisplayNotifications.java):

package com.example.projectswipe;

import globals.Globals;

import java.util.ArrayList;

import org.json.JSONArray;
import org.json.JSONException;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class DisplayNotifications extends Fragment {

    Globals global;
    JSONArray notificationsArray;
    ArrayList<String> notification = new ArrayList<String>();
    ListView l;

    public DisplayNotifications() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        Log.d("Test", "onCreate >>>>>>>>");
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.activity_display_notifications, container, false);
        Log.d("Test", "onCreateView >>>>>>>>");
        return view;
    }


    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        try {
            global = Globals.getInstance();
            notificationsArray = new JSONArray(global.getReplyString());
            System.out.println(">>>>>>>>>>"+notificationsArray);

            for(int i=0; i<notificationsArray.length(); i++){
                notification.add(notificationsArray.getJSONObject(i).getString("msg"));             
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }

        l = (ListView) getView().findViewById(R.id.notifications_listView);     
        NotificationsAdapter adapter = new NotificationsAdapter(getActivity(), notification);
        Log.d("Test", "onActivityCreated >>>>>>>>");
        l.setAdapter(adapter);
        //l.setOnItemClickListener(this);
        //l.setEmptyView(getActivity().findViewById(R.id.emptyProductDeals));
    }

}

class NotificationsAdapter extends ArrayAdapter<String>{

    Context contex;
    ArrayList<String> notifications;

    /*
     * Create a constructor which calls super(). In super(), we pass context, the singlerow.xml file, and the datasource
     */
    NotificationsAdapter(Context c, ArrayList<String> notifications){
        super(c, R.layout.single_notification, notifications);
        this.contex = c;
        this.notifications = notifications;
    }

    class MyViewHolder{
        TextView notification;

        MyViewHolder(View v){
            notification = (TextView) v.findViewById(R.id.notification_TextView);
        }

    }

    public View getView(int position, View convertView, ViewGroup parent){

        View root = convertView;
        MyViewHolder holder = null;

        if(root==null)
        {
            LayoutInflater inflater = (LayoutInflater) contex.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            root = inflater.inflate(R.layout.single_notification, parent, false);
            holder = new MyViewHolder(root);
            root.setTag(holder);
        }
        else{
            holder = (MyViewHolder) root.getTag();
        }

        holder.notification.setText(notifications.get(position));

        return root;

    }

}

我在这里做错了什么?我知道我错过了一些非常基本的东西,但我已经被困在这件事上好几个小时了。

感谢。

1 个答案:

答案 0 :(得分:0)

首先,您的主要布局不包含片段的容器(通常是FrameLayout),而FragmentTransaction不指定片段视图必须附加的位置。没有用户界面的片段保留了不将containerViewId作为参数的add()方法,这就是您没有看到任何内容的原因。

其次,你不能像在这里那样从后台线程调用FragmentManager。它必须始终在UI线程上完成。如果您使用AsyncTask,则意味着FragmentTransaction必须在onPostExecute()而不是doInBackground()中完成。但是,请确保在尝试提交片段事务之前启动了您的活动,否则您将收到IllegalStateException。一种常见的方法是取消onStop()中的AsyncTask,因此onPostExecute()之后不会调用onStop()

代码中的其他潜在问题:

  • 永远不要将ListView的高度设置为wrap_content。它可能会导致故障和性能问题。请改用match_parent,固定高度或重量。
  • 传递Fragment将在其Arguments Bundle中显示的数据,或者使Fragment在显示时加载自己的数据,而不是将数据加载到您的片段稍后将访问的某个全局变量中。您的Fragment不能依赖于全局变量在启动时正确设置的事实,因为系统可能会在应用程序不可见的任何时刻终止它并在以后恢复它。恢复应用程序时,还将恢复Activity,Fragment及其参数包,但不会恢复全局变量。