2013-05-15 36 views
10

Như tên đề xuất.
Tôi đã tải xuống Fragment mã từ đây, http://developer.android.com/shareables/training/FragmentBasics.zip.
Đây là ví dụ về Phân đoạn từ Trang web chính thức dành cho nhà phát triển Android. http://developer.android.com/training/basics/fragments/fragment-ui.htmlAndroid Fragment getArguments() trả về null

Đây là 's onCreate():

/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.news_articles); 

    // Check whether the activity is using the layout version with 
    // the fragment_container FrameLayout. If so, we must add the first fragment 
    if (findViewById(R.id.fragment_container) != null) { 

     // However, if we're being restored from a previous state, 
     // then we don't need to do anything and should return or else 
     // we could end up with overlapping fragments. 
     if (savedInstanceState != null) { 
      return; 
     } 

     // Create an instance of ExampleFragment 
     HeadlinesFragment fragment = new HeadlinesFragment(); 

     // In case this activity was started with special instructions from an Intent, 
     // pass the Intent's extras to the fragment as arguments 
     //fragment.setArguments(getIntent().getExtras()); 
     Bundle args= new Bundle(); 
     args.putString("category", "clothes"); 
     args.putString("item", "shirts"); 
     fragment.setArguments(args); 

     // Add the fragment to the 'fragment_container' FrameLayout 
     getSupportFragmentManager().beginTransaction() 
       .replace(R.id.fragment_container, fragment).commit(); 
    } 
} 

HeadlinesFragment.java' MainActivity.java s onCreate():

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    // We need to use a different list item layout for devices older than Honeycomb 
    int layout = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? 
      android.R.layout.simple_list_item_activated_1 : android.R.layout.simple_list_item_1; 

    Bundle args = getArguments(); 
    if (args == null) { 
     Toast.makeText(getActivity(), "arguments is null " , Toast.LENGTH_LONG).show(); 
    } else { 
     Toast.makeText(getActivity(), "text " + args , Toast.LENGTH_LONG).show(); 
    }   

    // Create an array adapter for the list view, using the Ipsum headlines array 
    setListAdapter(new ArrayAdapter<String>(getActivity(), layout, Ipsum.Headlines)); 

} 

Tôi đã đọc nhiều QA ở đây, như thế này Fragment getArguments() returns null, và nhiều khác liên quan đến setArguments() và , nhưng tôi vẫn bị kẹt.

Và tôi đã chuyển mã BundleToast-onAttach()onCreateView() với vô ích. Có gì sai với mã của tôi? Tôi nghĩ rằng tôi đang thiếu một cái gì đó, nhưng dunno nó là gì.
Vui lòng trợ giúp! Cảm ơn.

Chỉnh sửa:
Tôi sẽ nêu rõ ý định của mình rõ ràng hơn. Trong FragmentBasic mà tôi đã tải xuống, có MainActivity.java, HeadlinesFragment.java và ArticlesFragment.java. 'Giao tiếp' từ MainActivity.java đến ArticlesFragment.java không phải là vấn đề ở đây. Điều tôi muốn là gửi dữ liệu từ MainActivity.java đến HeadlinesFragment.java. Kết nối của họ như sau:

-------------------------------------- 
| MainActivity <-> HeadlinesFragment | 
|  |        | 
|  |>> ArticlesFragment   | 
-------------------------------------- 

HeadlinesFragment đang chạy ở thời gian chạy.

* Các mã này hoạt động khi sử dụng tiện ích Android với chiều rộng < 600px. Nhưng không hoạt động khi sử dụng trên máy tính bảng (> = 600px), Như đã được chứng minh bởi @ Tesla1984 bên dưới. Nhưng những gì tôi muốn là kết quả tương tự hoặc trên tiện ích < 600px và trên tiện ích> 600px.

+0

Tôi đã kiểm tra mã và 'getArguments()' không phải là rỗng. nếu mã ở trên là mã thực sự của bạn, tôi không nghĩ rằng có điều gì đó sai. nếu không, hãy kiểm tra các biến? – tesla1984

+0

@ tesla1984: bạn nhập mã vào phần nào? trong HeadlinesFragment.java hoặc ArticlesFragment.java? Nguyên nhân Bất cứ nơi nào tôi đặt 'getArguments()' trong HeadlinesFragment.java, tôi nhận được null. Cảm ơn. – tonny

+0

Một số lần nhật thực + ADT của tôi không thành công! .. Tôi cần dọn dẹp dự án và chạy lại .. –

Trả lời

1

Tôi đã giải quyết nó. Có vẻ như cách duy nhất để gửi dữ liệu từ MainActivity.java đến HeadlinesFragment.java là từ callbacks (Nếu bất kỳ ai biết cách khác, hãy đóng góp, sau đó chúng ta có một số cách khác bên cạnh việc này, giúp người khác với loại vấn đề này).

Mã chính từ là MainActivity.java của chức năng public Bundle getBundle() {}, sau đó đặt phần interface trên HeadlinesFragment.java, và thêm public Bundle getBundle();, và cuối cùng, gọi nó là từ HeadlinesFragment.java của onCreate.

Điều khiến tôi nhầm lẫn là fragment.setArguments(getIntent().getExtras()); trên số onCreate của MainActivity.java. Họ đặt mã đó ở đó và tôi tin rằng nó sẽ hoạt động vì đó là từ Hướng dẫn dành cho nhà phát triển chính thức của Android và APIhttp://developer.android.com/training/basics/fragments/fragment-ui.html, nhưng nó không hoạt động (bây giờ tôi tin rằng đoạn mã đó sẽ không làm gì cả). Vì vậy, bất cứ ai đọc hướng dẫn hoặc mẫu từ đó, mang nó với một hạt muối!

Các mã bên dưới, để mọi người có thể hiểu nó.

MainActivity.java:

/* 
* Copyright (C) 2012 The Android Open Source Project 
* 
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
*  http://www.apache.org/licenses/LICENSE-2.0 
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed under the License is distributed on an "AS IS" BASIS, 
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License. 
*/ 
package com.example.android.fragments; 

import android.os.Bundle; 
import android.support.v4.app.FragmentActivity; 
import android.support.v4.app.FragmentTransaction; 
import android.widget.Toast; 

public class MainActivity extends FragmentActivity 
     implements HeadlinesFragment.OnHeadlineSelectedListener { 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.news_articles); 

     // Check whether the activity is using the layout version with 
     // the fragment_container FrameLayout. If so, we must add the first fragment 
     if (findViewById(R.id.fragment_container) != null) { 

      // However, if we're being restored from a previous state, 
      // then we don't need to do anything and should return or else 
      // we could end up with overlapping fragments. 
      if (savedInstanceState != null) { 
       return; 
      } 

      Toast.makeText(getApplicationContext(), "activity", Toast.LENGTH_LONG).show(); 

      // Create an instance of ExampleFragment 
      HeadlinesFragment fragment = new HeadlinesFragment(); 

      // In case this activity was started with special instructions from an Intent, 
      // pass the Intent's extras to the fragment as arguments 
      fragment.setArguments(getIntent().getExtras()); 

      // Add the fragment to the 'fragment_container' FrameLayout 
      getSupportFragmentManager().beginTransaction() 
        .replace(R.id.fragment_container, fragment).commit(); 
     } 
    } 

    public void onArticleSelected(int position) { 
     // The user selected the headline of an article from the HeadlinesFragment 

     // Capture the article fragment from the activity layout 
     ArticleFragment articleFrag = (ArticleFragment) 
       getSupportFragmentManager().findFragmentById(R.id.article_fragment); 

     if (articleFrag != null) { 
      // If article frag is available, we're in two-pane layout... 

      // Call a method in the ArticleFragment to update its content 
      articleFrag.updateArticleView(position); 

     } else { 
      // If the frag is not available, we're in the one-pane layout and must swap frags... 

      // Create fragment and give it an argument for the selected article 
      ArticleFragment newFragment = new ArticleFragment(); 
      Bundle args = new Bundle(); 
      args.putInt(ArticleFragment.ARG_POSITION, position); 
      newFragment.setArguments(args); 
      FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 

      // Replace whatever is in the fragment_container view with this fragment, 
      // and add the transaction to the back stack so the user can navigate back 
      transaction.replace(R.id.fragment_container, newFragment); 
      transaction.addToBackStack(null); 

      // Commit the transaction 
      transaction.commit(); 
     } 
    } 

    public Bundle getBundle() { 
     Bundle args = new Bundle(); 
     args.putString("category", "cloths"); 
     args.putString("item", "shirts"); 
     return args; 
    } 
} 

HeadlinesFragment.java:

/* 
* Copyright (C) 2012 The Android Open Source Project 
* 
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
*  http://www.apache.org/licenses/LICENSE-2.0 
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed under the License is distributed on an "AS IS" BASIS, 
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License. 
*/ 
package com.example.android.fragments; 

import android.app.Activity; 
import android.os.Build; 
import android.os.Bundle; 
import android.support.v4.app.ListFragment; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.ArrayAdapter; 
import android.widget.ListView; 
import android.widget.Toast; 

public class HeadlinesFragment extends ListFragment { 
    OnHeadlineSelectedListener mCallback; 

    // The container Activity must implement this interface so the frag can deliver messages 
    public interface OnHeadlineSelectedListener { 
     /** Called by HeadlinesFragment when a list item is selected */ 
     public void onArticleSelected(int position); 
     public Bundle getBundle(); 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     Bundle bundle = mCallback.getBundle(); 
     Toast.makeText(getActivity(), "headline fragment " + bundle, Toast.LENGTH_LONG).show(); 

     // We need to use a different list item layout for devices older than Honeycomb 
     int layout = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? 
       android.R.layout.simple_list_item_activated_1 : android.R.layout.simple_list_item_1; 

     // Create an array adapter for the list view, using the Ipsum headlines array 
     setListAdapter(new ArrayAdapter<String>(getActivity(), layout, Ipsum.Headlines)); 

    } 

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

     return super.onCreateView(inflater, container, savedInstanceState); 
    } 

    @Override 
    public void onStart() { 
     super.onStart(); 

     // When in two-pane layout, set the listview to highlight the selected list item 
     // (We do this during onStart because at the point the listview is available.) 
     if (getFragmentManager().findFragmentById(R.id.article_fragment) != null) { 
      getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); 
     } 
    } 

    @Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 

     // This makes sure that the container activity has implemented 
     // the callback interface. If not, it throws an exception. 
     try { 
      mCallback = (OnHeadlineSelectedListener) activity; 
     } catch (ClassCastException e) { 
      throw new ClassCastException(activity.toString() 
        + " must implement OnHeadlineSelectedListener"); 
     } 
    } 

    @Override 
    public void onListItemClick(ListView l, View v, int position, long id) { 
     // Notify the parent activity of selected item 
     mCallback.onArticleSelected(position); 

     // Set the item as checked to be highlighted when in two-pane layout 
     getListView().setItemChecked(position, true); 
    } 
} 
+2

phương thức 'getArguments()' sẽ không là 'null' nếu bạn thiết lập các đối số. và tôi không đề nghị bạn sử dụng 'callback' để lấy' bó'. – tesla1984

+1

@ tesla1984: Vui lòng đọc câu hỏi của tôi. Và mã. Đối số đã được đặt. Bạn đã cố gắng để chạy mã? Với 'setArguments()' và 'getArguments()' đã thêm của bạn? Lúc đầu, tôi nghĩ rằng đó là cách, với set-getArguments(), nhưng tôi đã sai. Oh, và nếu bạn có giải pháp hoạt động, xin vui lòng gửi nó dưới đây. Tôi sẽ chấp nhận câu trả lời của bạn nếu các công trình của mã và không sử dụng các cuộc gọi lại. – tonny

0

Dường như bạn đang chèn cặp khóa và giá trị vào gói của mình. Có thể bạn cần tham chiếu giá trị khóa như trong getArguments().getString(category);

Theo tài liệu cho putString: Chèn giá trị chuỗi vào ánh xạ của gói này, thay thế bất kỳ giá trị hiện tại nào cho khóa đã cho. Khóa hoặc giá trị có thể là rỗng.

thông số chìa khóa một String, hoặc giá trị null một String, hoặc null

+1

'Chuỗi danh mục = getArguments(). GetString (" danh mục "); bạn có nghĩa là gì? Đã thử nó. Nó cho thấy lỗi, và chương trình sẽ đóng lại. Bạn cũng có thể đọc QA này. Tôi lấy ví dụ mã Toast từ đó [Fragment getArguments() trả về null] (http: // stackoverflow.com/questions/14970790/fragment-getarguments-returns-null) – tonny

7

@tonny

tôi đã tải về FragmentBasics.zip. tôi chỉ thay đổi tên đối số.đây là mã và kết quả pic.

MainActivity

public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.news_articles); 

    // Check whether the activity is using the layout version with 
    // the fragment_container FrameLayout. If so, we must add the first fragment 
    if (findViewById(R.id.fragment_container) != null) { 

     // However, if we're being restored from a previous state, 
     // then we don't need to do anything and should return or else 
     // we could end up with overlapping fragments. 
     if (savedInstanceState != null) { 
      return; 
     } 

     // Create an instance of ExampleFragment 
     HeadlinesFragment fragment = new HeadlinesFragment(); 

     // In case this activity was started with special instructions from an Intent, 
     // pass the Intent's extras to the fragment as arguments 
//   firstFragment.setArguments(getIntent().getExtras()); 
     //test 
     Bundle args= new Bundle(); 
     args.putString("category", "clothes"); 
     args.putString("item", "shirts"); 
     fragment.setArguments(args); 

     // Add the fragment to the 'fragment_container' FrameLayout 
     getSupportFragmentManager().beginTransaction() 
       .replace(R.id.fragment_container, fragment).commit(); 
    } 
} 

HeadlinesFragment

public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    // We need to use a different list item layout for devices older than Honeycomb 
    int layout = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? 
      android.R.layout.simple_list_item_activated_1 : android.R.layout.simple_list_item_1; 

    Bundle args = getArguments(); 
    if (args == null) { 
     Toast.makeText(getActivity(), "arguments is null " , Toast.LENGTH_LONG).show(); 
    } else { 
     Toast.makeText(getActivity(), "text " + args , Toast.LENGTH_LONG).show(); 
    }  

    // Create an array adapter for the list view, using the Ipsum headlines array 
    setListAdapter(new ArrayAdapter<String>(getActivity(), layout, Ipsum.Headlines)); 
} 

đây là kết quả

enter image description here

+0

Có, có vẻ như nó hoạt động khi sử dụng độ phân giải <600px. Hãy thử nó khi sử dụng nexus7 AVD. Nguyên nhân tất nhiên chúng tôi muốn kết quả tương tự khi sử dụng trên máy tính bảng hoặc trên điện thoại (> 600px và <600px). Cảm ơn – tonny

3

Tôi có cùng sự cố nhưng đã giải quyết được vấn đề này :)

Vấn đề của tôi là tôi có phần tử <fragment android:name=""> trong bố cục XML của Hoạt động. Do đó, onCreate() của Fragment được gọi trước các cuộc gọi trong mã Java, do đó không thiết lập các đối số.

Tôi đã xóa phần tử <fragment> khỏi bố cục XML của mình và nó hoạt động!

Các vấn đề liên quan