将数据从片段传递到另一个片段。片段未附加到上下文

时间:2018-08-25 09:09:32

标签: java android android-fragments kotlin fragment

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

错误:

  
    

原因:java.lang.IllegalStateException:片段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
    }
}

}

3 个答案:

答案 0 :(得分:0)

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

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)时,需要将片段附加到活动上才能获得上下文。在您刚刚初始化片段时,没有与之关联的上下文。

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

示例:

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)
    }
}

答案 1 :(得分:0)

    //------------------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);
        }
    }

答案 2 :(得分:0)

我之前曾遇到过这个问题,并从link的Android Developer网站解决了这个问题
建立一个接口很重要,这样片段可以通过它们的活动相互通信