【问题标题】:Passing data from fragment to another fragment. Fragment not attached to a context将数据从片段传递到另一个片段。片段未附加到上下文
【发布时间】:2018-08-25 09:09:32
【问题描述】:

我在将数据从片段传递到另一个片段时遇到问题。

错误:

原因:java.lang.IllegalStateException:Fragment FragmentBayar{5cd96b2} 未附加到上下文。 在 android.support.v4.app.Fragment.requireContext(Fragment.java:614) 在 android.support.v4.app.Fragment.getResources(Fragment.java:678) 在 android.support.v4.app.Fragment.getString(Fragment.java:700) 在 com.kensai.appkasir.fragment.FragmentBayar$Companion.newInstance(FragmentBayar.kt:45) 在 com.kensai.appkasir.FragmentActivity.onCreate(FragmentActivity.kt:55) 在 android.app.Activity.performCreate(Activity.java:6303) 在 android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108) 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2376)

这是我的片段

class FragmentBayar : Fragment(){
// order information
private lateinit var order: Orders

// data of menu before send
private var editList = ArrayList<EditQuantity>()
private lateinit var dataEditAdapter: EditQuantityAdapter

// data of menu after send
private var progressList = ArrayList<ProgressAntar>()
private lateinit var dataProgressAdapter: ProgressAntarAdapter

companion object {
    fun newInstance(order: Orders): FragmentBayar {
        val fragment = FragmentBayar()

        val bundle = Bundle()
        bundle.putParcelable(fragment.getString(R.string.key_pass_order), order)
        fragment.arguments = bundle
        return fragment
    }
}

// update array list of edit menu from clicked menu fragment
fun updateOrderEditList(menu: Menu){
    val editMenu = EditQuantity(menu,1,"")
    editList.add(0,editMenu)
    rec_edit_quantity.adapter.notifyDataSetChanged()
}

// read argumen as order object
private fun readBundle(bundle: Bundle?) {
    if (bundle != null) {
        order = bundle.getParcelable(getString(R.string.key_pass_order))
    }
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val view = inflater.inflate(R.layout.fragment_bayar, container, false)

    // get order
    readBundle(arguments)

    // change name order in header of view
    view.order_name.text = order.order

    // initial recyclerview edit item
    view.rec_edit_quantity.layoutManager = LinearLayoutManager(activity)
    view.rec_edit_quantity.isNestedScrollingEnabled = false
    view.rec_edit_quantity.hasFixedSize()
    view.rec_edit_quantity.adapter = EditQuantityAdapter(editList){ editPosition: Int -> editItemClicked(editPosition) }
    // initial recyclerview edit item data
    dataEditAdapter = EditQuantityAdapter(editList){ editPosition: Int -> editItemClicked(editPosition) }
    view.rec_edit_quantity.adapter = dataEditAdapter

    // initial recyclerview progress item
    view.rec_progress_antar.layoutManager = LinearLayoutManager(activity)
    view.rec_progress_antar.isNestedScrollingEnabled = false
    view.rec_progress_antar.hasFixedSize()
    view.rec_progress_antar.adapter = ProgressAntarAdapter(progressList)
    // initial recyclerview progress item data
    dataProgressAdapter = ProgressAntarAdapter(progressList)
    view.rec_progress_antar.adapter = dataProgressAdapter

    // setup pesan button
    btn_pesan.setOnClickListener {
        sendOrder()
    }

    // get detail service from server
    getOrderDetailService()

    return view
}

// call to get order detail from web service
private fun getOrderDetailService() {
    //temp
    progressList = getOrderData()
    dataProgressAdapter.updateData(progressList)
}

// send order list to server
private fun sendOrder(){
    val apiService : Service = Client.getClient()!!.create(Service::class.java)
    apiService.sendOrder(editList).enqueue(object : Callback<List<ProgressAntar>> {

        override fun onResponse(call: Call<List<ProgressAntar>>?, response: Response<List<ProgressAntar>>?) {
            if (response != null && response.isSuccessful) {
                val list = response.body()

                if (list == null || list.isEmpty()) {
                    Toast.makeText(activity, "Tidak ada daftar pembayaran", Toast.LENGTH_LONG).show()
                } else{
                    // empty edit list
                    editList = ArrayList()
                    dataEditAdapter.updateData(editList)
                    // refresh progress list
                    progressList = ArrayList(list)
                    dataProgressAdapter.updateData(progressList)
                }

            } else{
                Toast.makeText(activity, "Tidak ada daftar pembayaran", Toast.LENGTH_LONG).show()
            }
        }

        override fun onFailure(call: Call<List<ProgressAntar>>?, t: Throwable?) {
            Log.i("onFailure", t.toString())
            Toast.makeText(context, "Gagal", Toast.LENGTH_LONG).show()
        }
    })
}

// delete menu item before send
private fun editItemClicked(menuItem : Int){
    editList.removeAt(menuItem)
    rec_edit_quantity.adapter.notifyDataSetChanged()
}

// temp function
private fun getOrderData(): ArrayList<ProgressAntar>{
    val list = ArrayList<ProgressAntar>()
    list.add(ProgressAntar("1","Bakso",15000, 4,0,false))
    list.add(ProgressAntar("2","Teh Panas",  15000, 3,0, false))
    list.add(ProgressAntar("3","Mie Aceh",  15000, 5,5, true))
    list.add(ProgressAntar("4","Teh Dingin",  15000, 3,3, true))

    return list
}

override fun onResume() {
    super.onResume()
    getOrderDetailService()
}

}

这是活动类

class FragmentActivity : AppCompatActivity(), FragmentKategori.OnItemSelectedListener,
    FragmentMenu.OnItemSelectedListener {

// current order information
private lateinit var order: Orders

// action for item clicked on category fragment
override fun onCategoryItemSelected(category: Category) {
    val fragment = supportFragmentManager.findFragmentById(R.id.placeholder2) as FragmentMenu
    fragment.updateMenuList(category)
}

// action for item clicked on menu fragment
override fun onMenuItemSelected(menu: Menu) {
    val fragment = supportFragmentManager.findFragmentById(R.id.placeholder3) as FragmentBayar
    fragment.updateOrderEditList(menu)
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.layout_fragment)
    requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
    supportActionBar?.setDisplayHomeAsUpEnabled(true)

    // get bundle from previous activity
    val bundle = this.intent.extras

    // get order
    if(bundle.containsKey(getString(R.string.passOrder))){
        order = bundle.getParcelable(getString(R.string.passOrder))

    }
    else {
        Toast.makeText(this, "Something wrong", Toast.LENGTH_SHORT).show()
        finish()
    }

    val fragment1 = FragmentKategori()
    val fragment2 = FragmentMenu()
    val fragment3 = FragmentBayar.newInstance(order)

    supportFragmentManager.beginTransaction()
            .replace(R.id.placeholder1,fragment1)
            .replace(R.id.placeholder2,fragment2)
            .replace(R.id.placeholder3,fragment3)
            .commit()
}

override fun onCreateOptionsMenu(menu: android.view.Menu?): Boolean {
    menuInflater.inflate(R.menu.search,menu)
    return true
}

override fun onOptionsItemSelected(item: MenuItem?): Boolean {
    val id = item?.itemId

    if (id == R.id.search){
        swipeView()
    }else if (id == android.R.id.home){
        finish()
    }
    return super.onOptionsItemSelected(item)
}

// change view to search
private fun swipeView(){
    // show search view
    if (rec_menu.visibility == View.VISIBLE){
        rec_menu.visibility = View.GONE
        lay_search.visibility = View.VISIBLE
    }
    // show menu view
    else{
        rec_menu.visibility = View.VISIBLE
        lay_search.visibility = View.GONE
    }
}

}

【问题讨论】:

    标签: java android android-fragments kotlin fragment


    【解决方案1】:

    如您的跟踪所述,问题出在:

    fun newInstance(order: Orders): FragmentBayar {
        val fragment = FragmentBayar()
    
        val bundle = Bundle()
        /* here --> */bundle.putParcelable(fragment.getString(R.string.key_pass_order), order)
        fragment.arguments = bundle
        return fragment
    }
    

    当您调用fragment.getString(R.string.key_pass_order) 时,您需要将片段附加到活动以获取上下文。当您刚刚初始化片段时,没有关联的上下文。

    无论如何,将附加组件放入包中的通常做法是声明常量以写入/读取其属性。一个简短的解释是因为您不需要公开它,它们可以是类的私有范围。

    示例:

    companion object {
        private const val KEY_PASS_ORDER = "KEY_PASS_ORDER"
    
        fun newInstance(order: Orders): FragmentBayar {
            val fragment = FragmentBayar()
    
            val bundle = Bundle()
            bundle.putParcelable(KEY_PASS_ORDER, order)
            fragment.arguments = bundle
            return fragment
        }
    }
    
    private fun readBundle(bundle: Bundle?) {
        if (bundle != null) {
            order = bundle.getParcelable(KEY_PASS_ORDER)
        }
    }
    

    【讨论】:

      【解决方案2】:
          //------------------pass data one fragment to another fragment ------------
          First fragment
      
          import android.content.Context;
          import android.os.Bundle;
          import android.support.annotation.Nullable;
          import android.support.v4.app.Fragment;
          import android.view.LayoutInflater;
          import android.view.View;
          import android.view.ViewGroup;
          import android.widget.Button;
          import android.widget.EditText;
      
          public class FragmentOne extends Fragment {
      
              SendMessage SM;
      
              @Nullable
              @Override
              public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
                  View rootView = inflater.inflate(
                          R.layout.fragment_one, container, false);
                  return rootView;
      
      
              }
      
              @Override
              public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
                  super.onViewCreated(view, savedInstanceState);
      
                  Button btnPassData = (Button) view.findViewById(R.id.btnPassData);
                  final EditText inData = (EditText) view.findViewById(R.id.inMessage);
                  btnPassData.setOnClickListener(new View.OnClickListener() {
                      @Override
                      public void onClick(View v) {
                          SM.sendData(inData.getText().toString().trim());
                      }
                  });
      
              }
      
              interface SendMessage {
                  void sendData(String message);
              }
      
              @Override
              public void onAttach(Context context) {
                  super.onAttach(context);
      
                  try {
                      SM = (SendMessage) getActivity();
                  } catch (ClassCastException e) {
                      throw new ClassCastException("Error in retrieving data. Please try again");
                  }
              }
          }
      
          //------------------second fragment----------------------------
      
      
      
          import android.os.Bundle;
          import android.support.annotation.Nullable;
          import android.support.v4.app.Fragment;
          import android.view.LayoutInflater;
          import android.view.View;
          import android.view.ViewGroup;
          import android.widget.TextView;
      
          public class FragmentTwo extends Fragment {
      
              TextView txtData;
      
              @Nullable
              @Override
              public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
                  View rootView = inflater.inflate(
                          R.layout.fragment_two, container, false);
                  return rootView;
              }
      
              @Override
              public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
                  super.onViewCreated(view, savedInstanceState);
      
                  txtData = (TextView)view.findViewById(R.id.txtData);
              }
      
              protected void displayReceivedData(String message
      
      
      )
              {
                  txtData.setText("Data received: "+message);
              }
          }
      

      【讨论】:

        【解决方案3】:

        我以前遇到过这个问题,并从这个link的Android开发者网站解决它
        重要的是要构建一个接口,以便片段可以通过它们的活动在彼此之间进行通信

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-01-14
          • 1970-01-01
          • 2016-06-12
          • 1970-01-01
          • 2020-05-31
          • 1970-01-01
          相关资源
          最近更新 更多