如何修复空白片段?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何修复空白片段?相关的知识,希望对你有一定的参考价值。

我不熟悉android开发,正在尝试创建自己的应用。它应该使用YouTube数据API显示特定的YouTube频道。我从Android Studio中的标准底部导航模板开始,并在Github上使用以下项目提供了一些启动帮助。 https://github.com/stressGC/Remake-YouTube-Android

我必须在代码中更改一些东西,例如已弃用的http调用,以使其在新的Android APK上保持运行。从我的角度来看,一切似乎都很好:我可以看到API内容看起来不错,并且每个标题/描述/发布日期都放在了相应的变量中。日志中也没有错误消息。当我启动模拟器时,该应用程序运行正常。但是,一旦我切换到“仪表板”片段(放置代码的位置),它就为空。

DashboardFragment.java

public class DashboardFragment extends Fragment 
    private static String API_KEY = "hidden"; //normaler API key ohne limits, kein oauth
    private static String CHANNEL_ID = "hidden";
    private static String CHANNEL_GET_URL = "https://www.googleapis.com/youtube/v3/search?part=snippet&order=date&channelId="+CHANNEL_ID+"&maxResults=20&key="+API_KEY+"";

    private RecyclerView mList_videos = null;
    private VideoPostAdapter adapter = null;
    private ArrayList<YouTubeDataModel> mListData = new ArrayList<>();

    public DashboardFragment () 

    

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) 

        View view = inflater.inflate(R.layout.fragment_dashboard, container, false);
        mList_videos = (RecyclerView) view.findViewById(R.id.mList_videos);
        initList(mListData);
        new RequestYouTubeAPI().execute();
        return view;
    


    private void initList(ArrayList<YouTubeDataModel> mListData) 
        mList_videos.setLayoutManager(new LinearLayoutManager(getActivity()));
        adapter = new VideoPostAdapter(getActivity(), mListData);
        mList_videos.setAdapter(adapter);
    

    // create asynctask to get data from youtube
    private class RequestYouTubeAPI extends AsyncTask<Void, String, String>

        @Override
        protected void onPreExecute() 
            super.onPreExecute();
        

        @Override
        protected String doInBackground(Void... params) 
            URL url = null;
            String json = null;
            StringBuffer sb = new StringBuffer();

            try 
                url = new URL(CHANNEL_GET_URL);
             catch (MalformedURLException e) 
                e.printStackTrace();
            
            try 
                //HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                HttpURLConnection urlConnection = NetCipher.getHttpsURLConnection(url);
                InputStream in = new BufferedInputStream(urlConnection.getInputStream());
                BufferedReader br = new BufferedReader(new InputStreamReader(in));
                String inputLine = "";
                while ((inputLine = br.readLine()) != null) 
                    sb.append(inputLine);
                
                json = sb.toString();
                return json;

             catch (IOException e) 
                e.printStackTrace();
                return null;
            
        


        @Override
        protected void onPostExecute(String response) 
            super.onPostExecute(response);
            if(response != null)
                try 
                    JSONObject jsonObject = new JSONObject(response);
                    Log.e("response", jsonObject.toString());
                    mListData = parseVideoListFromResponse(jsonObject);
                    initList(mListData);
                    //adapter.notifyDataSetChanged();
                 catch (JSONException e) 
                    e.printStackTrace();
                
            
        
    

    public ArrayList<YouTubeDataModel> parseVideoListFromResponse(JSONObject jsonObject) 
        ArrayList<YouTubeDataModel> mList = new ArrayList<>();

        if (jsonObject.has("items")) 
            try 
                JSONArray jsonArray = jsonObject.getJSONArray("items");
                for (int i = 0; i < jsonArray.length(); i++) 
                    JSONObject json = jsonArray.getJSONObject(i);
                    if (json.has("id")) 
                        JSONObject jsonID = json.getJSONObject("id");
                        String video_id = "";
                        if (jsonID.has("videoId")) 
                            video_id = jsonID.getString("videoId");
                        
                        if (jsonID.has("kind")) 
                            if (jsonID.getString("kind").equals("youtube#video")) 
                                YouTubeDataModel youtubeObject = new YouTubeDataModel();
                                JSONObject jsonSnippet = json.getJSONObject("snippet");
                                String title = jsonSnippet.getString("title");
                                String description = jsonSnippet.getString("description");
                                String publishedAt = jsonSnippet.getString("publishedAt");
                                String thumbnail = jsonSnippet.getJSONObject("thumbnails").getJSONObject("high").getString("url");

                                youtubeObject.setTitle(title);
                                youtubeObject.setDescription(description);
                                youtubeObject.setPublishedAt(publishedAt);
                                youtubeObject.setThumbnail(thumbnail);
                                youtubeObject.setVideo_id(video_id);
                                mList.add(youtubeObject);

                            
                        
                    
                
             catch (JSONException e) 
                e.printStackTrace();
            
        

        return mList;
    

VideoPostAdapter.java

public class VideoPostAdapter extends RecyclerView.Adapter<VideoPostAdapter.YouTubePostHolder> 

    private ArrayList<YouTubeDataModel> dataSet;
    private Context mContext = null;

    public VideoPostAdapter(Context mContext, ArrayList<YouTubeDataModel> dataSet) 
        this.dataSet = dataSet;
        this.mContext = mContext;
    

    @NonNull
    @Override
    public YouTubePostHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) 
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.youtube_post_layout,parent,false);
        YouTubePostHolder postHolder = new YouTubePostHolder(view);
        return postHolder;
    

    @Override
    public void onBindViewHolder(@NonNull YouTubePostHolder holder, int position) 

        // set the views here
        TextView textViewTitle = holder.textViewTitle;
        TextView textViewDes = holder.textViewDes;
        TextView textViewDate = holder.textViewDate;
        ImageView ImageThumb = holder.ImageThumb;

        YouTubeDataModel object = dataSet.get(position);

        textViewTitle.setText(object.getTitle());
        textViewDes.setText(object.getDescription());
        textViewDate.setText(object.getPublishedAt());
        // image will be downloaded from url
    

    @Override
    public int getItemCount() 
        return dataSet.size();
    

    public static class YouTubePostHolder extends RecyclerView.ViewHolder
        TextView textViewTitle;
        TextView textViewDes;
        TextView textViewDate;
        ImageView ImageThumb;

        public YouTubePostHolder(@NonNull View itemView) 
            super(itemView);
            this.textViewTitle = (TextView) itemView.findViewById(R.id.textViewTitle);
            this.textViewDes = (TextView) itemView.findViewById(R.id.textViewDes);
            this.textViewDate = (TextView) itemView.findViewById(R.id.textViewDate);
            this.ImageThumb = (ImageView) itemView.findViewById(R.id.ImageThumb);
        
    

YouTubeDataModel.java

public class YouTubeDataModel 
    private String title = "";
    private String description = "";
    private String publishedAt = "";
    private String thumbnail = "";

    public String getVideo_id() 
        return video_id;
    

    public void setVideo_id(String video_id) 
        this.video_id = video_id;
    

    private String video_id = "";

    public String getTitle() 
        return title;
    

    public void setTitle(String title) 
        this.title = title;
    

    public String getDescription() 
        return description;
    

    public void setDescription(String description) 
        this.description = description;
    

    public String getPublishedAt() 
        return publishedAt;
    

    public void setPublishedAt(String publishedAt) 
        this.publishedAt = publishedAt;
    

    public String getThumbnail() 
        return thumbnail;
    

    public void setThumbnail(String thumbnail) 
        this.thumbnail = thumbnail;
    

youtube_post_layout.xml

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

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="200dp">

        <ImageView
            android:id="@+id/ImageThumb"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/colorPrimary"/>

        <TextView
            android:id="@+id/textViewDate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="published at"
            android:singleLine="true"
            android:layout_alignParentRight="true"
            android:layout_margin="5dp"
            android:textColor="@android:color/white"
            android:textSize="12dp"/>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_margin="10dp"
            android:orientation="vertical">

            <TextView
                android:id="@+id/textViewTitle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="video Title"
                android:singleLine="true"
                android:textColor="@android:color/white"
                android:textSize="22dp"/>

            <TextView
                android:id="@+id/textViewDes"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="video description"
                android:singleLine="true"
                android:textColor="@android:color/white"
                android:textSize="12dp"/>

        </LinearLayout>

    </RelativeLayout>

</LinearLayout>

fragment_dashboard.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/mList_videos"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

不幸的是,我不知道为什么片段仍然是空的。并且在Android Studio日志中没有任何错误,我真的希望您能为我提供帮助:/

答案

在您的RequestYouTubeAPI ASyncTask内部,您收到此错误代码:

         catch (IOException e) 
            e.printStackTrace();
            return null;
        

然后在onPostExecute中,您具有以下内容:

    @Override
    protected void onPostExecute(String response) 
        super.onPostExecute(response);
        if(response != null)
            try 
                JSONObject jsonObject = new JSONObject(response);
                Log.e("response", jsonObject.toString());
                mListData = parseVideoListFromResponse(jsonObject);
                initList(mListData);
                //adapter.notifyDataSetChanged();
             catch (JSONException e) 
                e.printStackTrace();
            
        
    

因此,如果出现错误,则将显示return null,并且如果为onPostExecute提供了null响应,则它什么都不做。

所以在这个地方您可能会出错,因此会有空白片段。


在解决此问题之前,您可以证明这种情况正在发生:

    @Override
    protected void onPostExecute(String response) 
        super.onPostExecute(response);
        if(response == null)
            Log.e("TUT", "We did not get a response, not updating the UI.");
         else 
            try 
                JSONObject jsonObject = new JSONObject(response);
                Log.e("response", jsonObject.toString());
                mListData = parseVideoListFromResponse(jsonObject);
                initList(mListData);
                //adapter.notifyDataSetChanged();
             catch (JSONException e) 
                e.printStackTrace();
            
        
    

您可以通过两种方式解决此问题:

doInBackground中将捕获更改为:

         catch (IOException e) 
            Log.e("TUT", "error", e);
            // Change this JSON to match what the parse expects, so you can show an error on the UI
            return "\"yourJson\":\"error!\"";
        

onPostExecute

        if(response == null)
            List errorList = new ArrayList();
            // Change this data model to show an error case to the UI
            errorList.add(new YouTubeDataModel("Error");
            mListData = errorList;
            initList(mListData);
         else 
            try 
                JSONObject jsonObject = new JSONObject(response);
                Log.e("response", jsonObject.toString());
                mListData = parseVideoListFromResponse(jsonObject);
                initList(mListData);
                //adapter.notifyDataSetChanged();
             catch (JSONException e) 
                e.printStackTrace();
            
        

希望有帮助,代码中可能还存在其他错误,但是如果API,Json,授权,互联网等出现问题,可能会发生这种情况。>

以上是关于如何修复空白片段?的主要内容,如果未能解决你的问题,请参考以下文章

如何修复在 OnCreateView() 中变为 null 的 List<>

使用选项卡第二次返回片段显示空白片段

片段布局为空白

片段内的LinearLayout总是在顶部留下空白

无法修复片段 NullPointerException 中的地图片段

片段中的Android webView显示空白页面