Saving and Restoring ListView (livedata) in FragmentsHow to save an Android Activity state using save instance state?Lazy load of images in ListViewHow to refresh Android listview?How to change color of Android ListView separator line?Maintain/Save/Restore scroll position when returning to a ListViewSpacing between listView Items AndroidonActivityResult is not being called in FragmentfindViewById in FragmentTrigger a method creates ListView in fragment from inner class, but content of ListView is disappeared sometimesEmpty savedInstanceState Bundle when restoring a Fragment after double Rotation in replacing Fragment

Is there a tool to measure the "maturity" of a code in Git?

Meaning of Swimming their horses

Is "you will become a subject matter expert" code for "you'll be working on your own 100% of the time"?

Output a Super Mario Image

What's the benefit of prohibiting the use of techniques/language constructs that have not been taught?

How would you control supersoldiers in a late iron-age society?

How To Make Earth's Oceans as Brackish as Lyr's

How do certain apps show new notifications when internet access is restricted to them?

What is the advantage and disadvantage of tail wheel so modern airplane is not use it anymore?

In what state are satellites left in when they are left in a graveyard orbit?

Planar regular languages

International Orange?

Make 2019 with single digits

Are there objective criteria for classifying consonance v. dissonance?

geschafft or geschaffen? which one is past participle of schaffen?

Why is the car dealer insisting on a loan instead of cash?

Where is it? - The Google Earth Challenge Ep. 3

Permutations in Disguise

Would a hotel in Turkey question absence of entry stamp in passport?

Isometries of convex hypersurfaces

Read string of any length in C

Which is the current decimal separator?

'Overwrote' files, space still occupied, are they lost?

What 68-pin connector is this on my 2.5" solid state drive?



Saving and Restoring ListView (livedata) in Fragments


How to save an Android Activity state using save instance state?Lazy load of images in ListViewHow to refresh Android listview?How to change color of Android ListView separator line?Maintain/Save/Restore scroll position when returning to a ListViewSpacing between listView Items AndroidonActivityResult is not being called in FragmentfindViewById in FragmentTrigger a method creates ListView in fragment from inner class, but content of ListView is disappeared sometimesEmpty savedInstanceState Bundle when restoring a Fragment after double Rotation in replacing Fragment






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








0















I'm trying to make a Todo app. I have succesfully implemented livedata and listview in fragments (fragments are default from the project quickstart template). My problem which I can't resolve is saving those todo's so they are still there upon launching app back again.



Browsed tons of answers on stack and blogs and read about whole lifecycle but I still don't get it. I finally gave up and this is what (not working) code I end up with atm:



FragmentLifeCycle to save "state" of the listOfToDoThings



class FragmentLifeCycle : Fragment() 

private var state: Parcelable? = null

override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
Log.d("Lifecycle Info", "onCreate()")



override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
Log.d("Lifecycle Info", "onCreateView()")
return inflater.inflate(R.layout.activity_main, container, false)


override fun onActivityCreated(savedInstanceState: Bundle?)
super.onActivityCreated(savedInstanceState)
Log.d("Lifecycle Info", "onActivityCreated()")



override fun onResume()
super.onResume()

if (state != null)
Log.i("Lifecycle Info", "onResume finally works")
listOfToDoThings.onRestoreInstanceState(state)


Log.d("Lifecycle Info", "onResume()")



override fun onPause()
state = listOfToDoThings.onSaveInstanceState()
super.onPause()
Log.d("Lifecycle Info", "onStop()")





which throws nullpointer:



'android.os.Parcelable android.widget.ListView.onSaveInstanceState()' on a null object reference



And Main_Activity cleared out of tons of commented not-working solutions:



class MainActivity : AppCompatActivity()

private var mSectionsPagerAdapter: SectionsPagerAdapter? = null

override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

setSupportActionBar(toolbar)
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = SectionsPagerAdapter(supportFragmentManager)

// Set up the ViewPager with the sections adapter.
container.adapter = mSectionsPagerAdapter

val fragmentManager = this.supportFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()

val fragmentLifeCycle = FragmentLifeCycle()
fragmentTransaction.add(R.id.container, fragmentLifeCycle, "Lifecycle Fragment")
fragmentTransaction.commit()



override fun onCreateOptionsMenu(menu: Menu): Boolean
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.menu_main, menu)


return true


override fun onOptionsItemSelected(item: MenuItem): Boolean
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
val id = item.itemId

if (id == R.id.action_settings)
return true


return super.onOptionsItemSelected(item)


/**
* A [FragmentPagerAdapter] that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
inner class SectionsPagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm)

override fun getItem(position: Int): Fragment
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
return PlaceholderFragment.newInstance(position + 1)


override fun getCount(): Int
// Show 3 total pages.
return 4




/**
* A placeholder fragment containing a simple view.
*/
class PlaceholderFragment : Fragment(), Renderer<TodoModel>

private lateinit var store: TodoStore

override fun render(model: LiveData<TodoModel>)
model.observe(this, Observer newState ->
listOfToDoThings.adapter = TodoAdapter(requireContext(), newState?.todos ?: listOf())
)




private fun openDialog()
val options = resources.getStringArray(R.array.filter_options).asList()
requireContext().selector(getString(R.string.filter_title), options) _, i ->
val visible = when (i)
1 -> Visibility.Active()
2 -> Visibility.Completed()
else -> Visibility.All()

store.dispatch(SetVisibility(visible))



private val mapStateToProps = Function<TodoModel, TodoModel>
val keep: (Todo) -> Boolean = when(it.visibility)

is Visibility.All -> _ -> true
is Visibility.Active -> t: Todo -> !t.status
is Visibility.Completed -> t: Todo -> t.status


return@Function it.copy(todos = it.todos.filter keep(it) )


override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View?

val rootView = inflater.inflate(R.layout.fragment_main, container, false)
rootView.section_label.text = getString(R.string.section_format, arguments?.getInt(ARG_SECTION_NUMBER))

@SuppressLint("SetTextI18n")
when(arguments?.getInt(ARG_SECTION_NUMBER))
1 -> rootView.section_name.text = "Daily Life"
2 -> rootView.section_name.text = "Work and College"
3 -> rootView.section_name.text = "Visits"
4 -> rootView.section_name.text = "Shop"


store = ViewModelProviders.of(this).get(TodoStore::class.java)
store.subscribe(this, mapStateToProps)

// Add task and then reset editText component
rootView.addNewToDo.setOnClickListener
store.dispatch(AddTodo(editText.text.toString()))
editText.text = null


rootView.filter.setOnClickListener openDialog()

// Press to change status of task
rootView.listOfToDoThings.adapter = TodoAdapter(requireContext(), listOf())
rootView.listOfToDoThings.setOnItemClickListener _, _, _, id ->
store.dispatch(ToggleTodo(id))


// Hold to delete task
rootView.listOfToDoThings.setOnItemLongClickListener _, _, _, id ->
store.dispatch(RemoveTodo(id))
true


return rootView




companion object
/**
* The fragment argument representing the section number for this
* fragment.
*/
private val ARG_SECTION_NUMBER = "section_number"

/**
* Returns a new instance of this fragment for the given section
* number.
*/
fun newInstance(sectionNumber: Int): PlaceholderFragment
val fragment = PlaceholderFragment()
val args = Bundle()
args.putInt(ARG_SECTION_NUMBER, sectionNumber)
fragment.arguments = args
return fragment






Not sure if its usefull but that's how TodoStore.kt looks like:



class TodoStore : Store<TodoModel>, ViewModel()

private val state: MutableLiveData<TodoModel> = MutableLiveData()

// Start with all tasks visible regardless of previous state
private val initState = TodoModel(listOf(), Visibility.All())

override fun dispatch(action: Action)
state.value = reduce(state.value, action)



private fun reduce(state: TodoModel?, action: Action): TodoModel
val newState= state ?: initState

return when(action)

// Adds stuff upon creating new todo
is AddTodo -> newState.copy(
todos = newState.todos.toMutableList().apply
add(Todo(action.text, action.id))

)

is ToggleTodo -> newState.copy(
todos = newState.todos.map
if (it.id == action.id)
it.copy(status = !it.status)
else it
as MutableList<Todo>
)

is SetVisibility -> newState.copy(
visibility = action.visibility
)

is RemoveTodo -> newState.copy(
todos = newState.todos.filter
it.id != action.id
as MutableList<Todo>
)



override fun subscribe(renderer: Renderer<TodoModel>, func: Function<TodoModel, TodoModel>)
renderer.render(Transformations.map(state, func))












share|improve this question
































    0















    I'm trying to make a Todo app. I have succesfully implemented livedata and listview in fragments (fragments are default from the project quickstart template). My problem which I can't resolve is saving those todo's so they are still there upon launching app back again.



    Browsed tons of answers on stack and blogs and read about whole lifecycle but I still don't get it. I finally gave up and this is what (not working) code I end up with atm:



    FragmentLifeCycle to save "state" of the listOfToDoThings



    class FragmentLifeCycle : Fragment() 

    private var state: Parcelable? = null

    override fun onCreate(savedInstanceState: Bundle?)
    super.onCreate(savedInstanceState)
    Log.d("Lifecycle Info", "onCreate()")



    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
    Log.d("Lifecycle Info", "onCreateView()")
    return inflater.inflate(R.layout.activity_main, container, false)


    override fun onActivityCreated(savedInstanceState: Bundle?)
    super.onActivityCreated(savedInstanceState)
    Log.d("Lifecycle Info", "onActivityCreated()")



    override fun onResume()
    super.onResume()

    if (state != null)
    Log.i("Lifecycle Info", "onResume finally works")
    listOfToDoThings.onRestoreInstanceState(state)


    Log.d("Lifecycle Info", "onResume()")



    override fun onPause()
    state = listOfToDoThings.onSaveInstanceState()
    super.onPause()
    Log.d("Lifecycle Info", "onStop()")





    which throws nullpointer:



    'android.os.Parcelable android.widget.ListView.onSaveInstanceState()' on a null object reference



    And Main_Activity cleared out of tons of commented not-working solutions:



    class MainActivity : AppCompatActivity()

    private var mSectionsPagerAdapter: SectionsPagerAdapter? = null

    override fun onCreate(savedInstanceState: Bundle?)
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    setSupportActionBar(toolbar)
    // Create the adapter that will return a fragment for each of the three
    // primary sections of the activity.
    mSectionsPagerAdapter = SectionsPagerAdapter(supportFragmentManager)

    // Set up the ViewPager with the sections adapter.
    container.adapter = mSectionsPagerAdapter

    val fragmentManager = this.supportFragmentManager
    val fragmentTransaction = fragmentManager.beginTransaction()

    val fragmentLifeCycle = FragmentLifeCycle()
    fragmentTransaction.add(R.id.container, fragmentLifeCycle, "Lifecycle Fragment")
    fragmentTransaction.commit()



    override fun onCreateOptionsMenu(menu: Menu): Boolean
    // Inflate the menu; this adds items to the action bar if it is present.
    menuInflater.inflate(R.menu.menu_main, menu)


    return true


    override fun onOptionsItemSelected(item: MenuItem): Boolean
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    val id = item.itemId

    if (id == R.id.action_settings)
    return true


    return super.onOptionsItemSelected(item)


    /**
    * A [FragmentPagerAdapter] that returns a fragment corresponding to
    * one of the sections/tabs/pages.
    */
    inner class SectionsPagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm)

    override fun getItem(position: Int): Fragment
    // getItem is called to instantiate the fragment for the given page.
    // Return a PlaceholderFragment (defined as a static inner class below).
    return PlaceholderFragment.newInstance(position + 1)


    override fun getCount(): Int
    // Show 3 total pages.
    return 4




    /**
    * A placeholder fragment containing a simple view.
    */
    class PlaceholderFragment : Fragment(), Renderer<TodoModel>

    private lateinit var store: TodoStore

    override fun render(model: LiveData<TodoModel>)
    model.observe(this, Observer newState ->
    listOfToDoThings.adapter = TodoAdapter(requireContext(), newState?.todos ?: listOf())
    )




    private fun openDialog()
    val options = resources.getStringArray(R.array.filter_options).asList()
    requireContext().selector(getString(R.string.filter_title), options) _, i ->
    val visible = when (i)
    1 -> Visibility.Active()
    2 -> Visibility.Completed()
    else -> Visibility.All()

    store.dispatch(SetVisibility(visible))



    private val mapStateToProps = Function<TodoModel, TodoModel>
    val keep: (Todo) -> Boolean = when(it.visibility)

    is Visibility.All -> _ -> true
    is Visibility.Active -> t: Todo -> !t.status
    is Visibility.Completed -> t: Todo -> t.status


    return@Function it.copy(todos = it.todos.filter keep(it) )


    override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
    ): View?

    val rootView = inflater.inflate(R.layout.fragment_main, container, false)
    rootView.section_label.text = getString(R.string.section_format, arguments?.getInt(ARG_SECTION_NUMBER))

    @SuppressLint("SetTextI18n")
    when(arguments?.getInt(ARG_SECTION_NUMBER))
    1 -> rootView.section_name.text = "Daily Life"
    2 -> rootView.section_name.text = "Work and College"
    3 -> rootView.section_name.text = "Visits"
    4 -> rootView.section_name.text = "Shop"


    store = ViewModelProviders.of(this).get(TodoStore::class.java)
    store.subscribe(this, mapStateToProps)

    // Add task and then reset editText component
    rootView.addNewToDo.setOnClickListener
    store.dispatch(AddTodo(editText.text.toString()))
    editText.text = null


    rootView.filter.setOnClickListener openDialog()

    // Press to change status of task
    rootView.listOfToDoThings.adapter = TodoAdapter(requireContext(), listOf())
    rootView.listOfToDoThings.setOnItemClickListener _, _, _, id ->
    store.dispatch(ToggleTodo(id))


    // Hold to delete task
    rootView.listOfToDoThings.setOnItemLongClickListener _, _, _, id ->
    store.dispatch(RemoveTodo(id))
    true


    return rootView




    companion object
    /**
    * The fragment argument representing the section number for this
    * fragment.
    */
    private val ARG_SECTION_NUMBER = "section_number"

    /**
    * Returns a new instance of this fragment for the given section
    * number.
    */
    fun newInstance(sectionNumber: Int): PlaceholderFragment
    val fragment = PlaceholderFragment()
    val args = Bundle()
    args.putInt(ARG_SECTION_NUMBER, sectionNumber)
    fragment.arguments = args
    return fragment






    Not sure if its usefull but that's how TodoStore.kt looks like:



    class TodoStore : Store<TodoModel>, ViewModel()

    private val state: MutableLiveData<TodoModel> = MutableLiveData()

    // Start with all tasks visible regardless of previous state
    private val initState = TodoModel(listOf(), Visibility.All())

    override fun dispatch(action: Action)
    state.value = reduce(state.value, action)



    private fun reduce(state: TodoModel?, action: Action): TodoModel
    val newState= state ?: initState

    return when(action)

    // Adds stuff upon creating new todo
    is AddTodo -> newState.copy(
    todos = newState.todos.toMutableList().apply
    add(Todo(action.text, action.id))

    )

    is ToggleTodo -> newState.copy(
    todos = newState.todos.map
    if (it.id == action.id)
    it.copy(status = !it.status)
    else it
    as MutableList<Todo>
    )

    is SetVisibility -> newState.copy(
    visibility = action.visibility
    )

    is RemoveTodo -> newState.copy(
    todos = newState.todos.filter
    it.id != action.id
    as MutableList<Todo>
    )



    override fun subscribe(renderer: Renderer<TodoModel>, func: Function<TodoModel, TodoModel>)
    renderer.render(Transformations.map(state, func))












    share|improve this question




























      0












      0








      0








      I'm trying to make a Todo app. I have succesfully implemented livedata and listview in fragments (fragments are default from the project quickstart template). My problem which I can't resolve is saving those todo's so they are still there upon launching app back again.



      Browsed tons of answers on stack and blogs and read about whole lifecycle but I still don't get it. I finally gave up and this is what (not working) code I end up with atm:



      FragmentLifeCycle to save "state" of the listOfToDoThings



      class FragmentLifeCycle : Fragment() 

      private var state: Parcelable? = null

      override fun onCreate(savedInstanceState: Bundle?)
      super.onCreate(savedInstanceState)
      Log.d("Lifecycle Info", "onCreate()")



      override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
      Log.d("Lifecycle Info", "onCreateView()")
      return inflater.inflate(R.layout.activity_main, container, false)


      override fun onActivityCreated(savedInstanceState: Bundle?)
      super.onActivityCreated(savedInstanceState)
      Log.d("Lifecycle Info", "onActivityCreated()")



      override fun onResume()
      super.onResume()

      if (state != null)
      Log.i("Lifecycle Info", "onResume finally works")
      listOfToDoThings.onRestoreInstanceState(state)


      Log.d("Lifecycle Info", "onResume()")



      override fun onPause()
      state = listOfToDoThings.onSaveInstanceState()
      super.onPause()
      Log.d("Lifecycle Info", "onStop()")





      which throws nullpointer:



      'android.os.Parcelable android.widget.ListView.onSaveInstanceState()' on a null object reference



      And Main_Activity cleared out of tons of commented not-working solutions:



      class MainActivity : AppCompatActivity()

      private var mSectionsPagerAdapter: SectionsPagerAdapter? = null

      override fun onCreate(savedInstanceState: Bundle?)
      super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_main)

      setSupportActionBar(toolbar)
      // Create the adapter that will return a fragment for each of the three
      // primary sections of the activity.
      mSectionsPagerAdapter = SectionsPagerAdapter(supportFragmentManager)

      // Set up the ViewPager with the sections adapter.
      container.adapter = mSectionsPagerAdapter

      val fragmentManager = this.supportFragmentManager
      val fragmentTransaction = fragmentManager.beginTransaction()

      val fragmentLifeCycle = FragmentLifeCycle()
      fragmentTransaction.add(R.id.container, fragmentLifeCycle, "Lifecycle Fragment")
      fragmentTransaction.commit()



      override fun onCreateOptionsMenu(menu: Menu): Boolean
      // Inflate the menu; this adds items to the action bar if it is present.
      menuInflater.inflate(R.menu.menu_main, menu)


      return true


      override fun onOptionsItemSelected(item: MenuItem): Boolean
      // Handle action bar item clicks here. The action bar will
      // automatically handle clicks on the Home/Up button, so long
      // as you specify a parent activity in AndroidManifest.xml.
      val id = item.itemId

      if (id == R.id.action_settings)
      return true


      return super.onOptionsItemSelected(item)


      /**
      * A [FragmentPagerAdapter] that returns a fragment corresponding to
      * one of the sections/tabs/pages.
      */
      inner class SectionsPagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm)

      override fun getItem(position: Int): Fragment
      // getItem is called to instantiate the fragment for the given page.
      // Return a PlaceholderFragment (defined as a static inner class below).
      return PlaceholderFragment.newInstance(position + 1)


      override fun getCount(): Int
      // Show 3 total pages.
      return 4




      /**
      * A placeholder fragment containing a simple view.
      */
      class PlaceholderFragment : Fragment(), Renderer<TodoModel>

      private lateinit var store: TodoStore

      override fun render(model: LiveData<TodoModel>)
      model.observe(this, Observer newState ->
      listOfToDoThings.adapter = TodoAdapter(requireContext(), newState?.todos ?: listOf())
      )




      private fun openDialog()
      val options = resources.getStringArray(R.array.filter_options).asList()
      requireContext().selector(getString(R.string.filter_title), options) _, i ->
      val visible = when (i)
      1 -> Visibility.Active()
      2 -> Visibility.Completed()
      else -> Visibility.All()

      store.dispatch(SetVisibility(visible))



      private val mapStateToProps = Function<TodoModel, TodoModel>
      val keep: (Todo) -> Boolean = when(it.visibility)

      is Visibility.All -> _ -> true
      is Visibility.Active -> t: Todo -> !t.status
      is Visibility.Completed -> t: Todo -> t.status


      return@Function it.copy(todos = it.todos.filter keep(it) )


      override fun onCreateView(
      inflater: LayoutInflater, container: ViewGroup?,
      savedInstanceState: Bundle?
      ): View?

      val rootView = inflater.inflate(R.layout.fragment_main, container, false)
      rootView.section_label.text = getString(R.string.section_format, arguments?.getInt(ARG_SECTION_NUMBER))

      @SuppressLint("SetTextI18n")
      when(arguments?.getInt(ARG_SECTION_NUMBER))
      1 -> rootView.section_name.text = "Daily Life"
      2 -> rootView.section_name.text = "Work and College"
      3 -> rootView.section_name.text = "Visits"
      4 -> rootView.section_name.text = "Shop"


      store = ViewModelProviders.of(this).get(TodoStore::class.java)
      store.subscribe(this, mapStateToProps)

      // Add task and then reset editText component
      rootView.addNewToDo.setOnClickListener
      store.dispatch(AddTodo(editText.text.toString()))
      editText.text = null


      rootView.filter.setOnClickListener openDialog()

      // Press to change status of task
      rootView.listOfToDoThings.adapter = TodoAdapter(requireContext(), listOf())
      rootView.listOfToDoThings.setOnItemClickListener _, _, _, id ->
      store.dispatch(ToggleTodo(id))


      // Hold to delete task
      rootView.listOfToDoThings.setOnItemLongClickListener _, _, _, id ->
      store.dispatch(RemoveTodo(id))
      true


      return rootView




      companion object
      /**
      * The fragment argument representing the section number for this
      * fragment.
      */
      private val ARG_SECTION_NUMBER = "section_number"

      /**
      * Returns a new instance of this fragment for the given section
      * number.
      */
      fun newInstance(sectionNumber: Int): PlaceholderFragment
      val fragment = PlaceholderFragment()
      val args = Bundle()
      args.putInt(ARG_SECTION_NUMBER, sectionNumber)
      fragment.arguments = args
      return fragment






      Not sure if its usefull but that's how TodoStore.kt looks like:



      class TodoStore : Store<TodoModel>, ViewModel()

      private val state: MutableLiveData<TodoModel> = MutableLiveData()

      // Start with all tasks visible regardless of previous state
      private val initState = TodoModel(listOf(), Visibility.All())

      override fun dispatch(action: Action)
      state.value = reduce(state.value, action)



      private fun reduce(state: TodoModel?, action: Action): TodoModel
      val newState= state ?: initState

      return when(action)

      // Adds stuff upon creating new todo
      is AddTodo -> newState.copy(
      todos = newState.todos.toMutableList().apply
      add(Todo(action.text, action.id))

      )

      is ToggleTodo -> newState.copy(
      todos = newState.todos.map
      if (it.id == action.id)
      it.copy(status = !it.status)
      else it
      as MutableList<Todo>
      )

      is SetVisibility -> newState.copy(
      visibility = action.visibility
      )

      is RemoveTodo -> newState.copy(
      todos = newState.todos.filter
      it.id != action.id
      as MutableList<Todo>
      )



      override fun subscribe(renderer: Renderer<TodoModel>, func: Function<TodoModel, TodoModel>)
      renderer.render(Transformations.map(state, func))












      share|improve this question
















      I'm trying to make a Todo app. I have succesfully implemented livedata and listview in fragments (fragments are default from the project quickstart template). My problem which I can't resolve is saving those todo's so they are still there upon launching app back again.



      Browsed tons of answers on stack and blogs and read about whole lifecycle but I still don't get it. I finally gave up and this is what (not working) code I end up with atm:



      FragmentLifeCycle to save "state" of the listOfToDoThings



      class FragmentLifeCycle : Fragment() 

      private var state: Parcelable? = null

      override fun onCreate(savedInstanceState: Bundle?)
      super.onCreate(savedInstanceState)
      Log.d("Lifecycle Info", "onCreate()")



      override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
      Log.d("Lifecycle Info", "onCreateView()")
      return inflater.inflate(R.layout.activity_main, container, false)


      override fun onActivityCreated(savedInstanceState: Bundle?)
      super.onActivityCreated(savedInstanceState)
      Log.d("Lifecycle Info", "onActivityCreated()")



      override fun onResume()
      super.onResume()

      if (state != null)
      Log.i("Lifecycle Info", "onResume finally works")
      listOfToDoThings.onRestoreInstanceState(state)


      Log.d("Lifecycle Info", "onResume()")



      override fun onPause()
      state = listOfToDoThings.onSaveInstanceState()
      super.onPause()
      Log.d("Lifecycle Info", "onStop()")





      which throws nullpointer:



      'android.os.Parcelable android.widget.ListView.onSaveInstanceState()' on a null object reference



      And Main_Activity cleared out of tons of commented not-working solutions:



      class MainActivity : AppCompatActivity()

      private var mSectionsPagerAdapter: SectionsPagerAdapter? = null

      override fun onCreate(savedInstanceState: Bundle?)
      super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_main)

      setSupportActionBar(toolbar)
      // Create the adapter that will return a fragment for each of the three
      // primary sections of the activity.
      mSectionsPagerAdapter = SectionsPagerAdapter(supportFragmentManager)

      // Set up the ViewPager with the sections adapter.
      container.adapter = mSectionsPagerAdapter

      val fragmentManager = this.supportFragmentManager
      val fragmentTransaction = fragmentManager.beginTransaction()

      val fragmentLifeCycle = FragmentLifeCycle()
      fragmentTransaction.add(R.id.container, fragmentLifeCycle, "Lifecycle Fragment")
      fragmentTransaction.commit()



      override fun onCreateOptionsMenu(menu: Menu): Boolean
      // Inflate the menu; this adds items to the action bar if it is present.
      menuInflater.inflate(R.menu.menu_main, menu)


      return true


      override fun onOptionsItemSelected(item: MenuItem): Boolean
      // Handle action bar item clicks here. The action bar will
      // automatically handle clicks on the Home/Up button, so long
      // as you specify a parent activity in AndroidManifest.xml.
      val id = item.itemId

      if (id == R.id.action_settings)
      return true


      return super.onOptionsItemSelected(item)


      /**
      * A [FragmentPagerAdapter] that returns a fragment corresponding to
      * one of the sections/tabs/pages.
      */
      inner class SectionsPagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm)

      override fun getItem(position: Int): Fragment
      // getItem is called to instantiate the fragment for the given page.
      // Return a PlaceholderFragment (defined as a static inner class below).
      return PlaceholderFragment.newInstance(position + 1)


      override fun getCount(): Int
      // Show 3 total pages.
      return 4




      /**
      * A placeholder fragment containing a simple view.
      */
      class PlaceholderFragment : Fragment(), Renderer<TodoModel>

      private lateinit var store: TodoStore

      override fun render(model: LiveData<TodoModel>)
      model.observe(this, Observer newState ->
      listOfToDoThings.adapter = TodoAdapter(requireContext(), newState?.todos ?: listOf())
      )




      private fun openDialog()
      val options = resources.getStringArray(R.array.filter_options).asList()
      requireContext().selector(getString(R.string.filter_title), options) _, i ->
      val visible = when (i)
      1 -> Visibility.Active()
      2 -> Visibility.Completed()
      else -> Visibility.All()

      store.dispatch(SetVisibility(visible))



      private val mapStateToProps = Function<TodoModel, TodoModel>
      val keep: (Todo) -> Boolean = when(it.visibility)

      is Visibility.All -> _ -> true
      is Visibility.Active -> t: Todo -> !t.status
      is Visibility.Completed -> t: Todo -> t.status


      return@Function it.copy(todos = it.todos.filter keep(it) )


      override fun onCreateView(
      inflater: LayoutInflater, container: ViewGroup?,
      savedInstanceState: Bundle?
      ): View?

      val rootView = inflater.inflate(R.layout.fragment_main, container, false)
      rootView.section_label.text = getString(R.string.section_format, arguments?.getInt(ARG_SECTION_NUMBER))

      @SuppressLint("SetTextI18n")
      when(arguments?.getInt(ARG_SECTION_NUMBER))
      1 -> rootView.section_name.text = "Daily Life"
      2 -> rootView.section_name.text = "Work and College"
      3 -> rootView.section_name.text = "Visits"
      4 -> rootView.section_name.text = "Shop"


      store = ViewModelProviders.of(this).get(TodoStore::class.java)
      store.subscribe(this, mapStateToProps)

      // Add task and then reset editText component
      rootView.addNewToDo.setOnClickListener
      store.dispatch(AddTodo(editText.text.toString()))
      editText.text = null


      rootView.filter.setOnClickListener openDialog()

      // Press to change status of task
      rootView.listOfToDoThings.adapter = TodoAdapter(requireContext(), listOf())
      rootView.listOfToDoThings.setOnItemClickListener _, _, _, id ->
      store.dispatch(ToggleTodo(id))


      // Hold to delete task
      rootView.listOfToDoThings.setOnItemLongClickListener _, _, _, id ->
      store.dispatch(RemoveTodo(id))
      true


      return rootView




      companion object
      /**
      * The fragment argument representing the section number for this
      * fragment.
      */
      private val ARG_SECTION_NUMBER = "section_number"

      /**
      * Returns a new instance of this fragment for the given section
      * number.
      */
      fun newInstance(sectionNumber: Int): PlaceholderFragment
      val fragment = PlaceholderFragment()
      val args = Bundle()
      args.putInt(ARG_SECTION_NUMBER, sectionNumber)
      fragment.arguments = args
      return fragment






      Not sure if its usefull but that's how TodoStore.kt looks like:



      class TodoStore : Store<TodoModel>, ViewModel()

      private val state: MutableLiveData<TodoModel> = MutableLiveData()

      // Start with all tasks visible regardless of previous state
      private val initState = TodoModel(listOf(), Visibility.All())

      override fun dispatch(action: Action)
      state.value = reduce(state.value, action)



      private fun reduce(state: TodoModel?, action: Action): TodoModel
      val newState= state ?: initState

      return when(action)

      // Adds stuff upon creating new todo
      is AddTodo -> newState.copy(
      todos = newState.todos.toMutableList().apply
      add(Todo(action.text, action.id))

      )

      is ToggleTodo -> newState.copy(
      todos = newState.todos.map
      if (it.id == action.id)
      it.copy(status = !it.status)
      else it
      as MutableList<Todo>
      )

      is SetVisibility -> newState.copy(
      visibility = action.visibility
      )

      is RemoveTodo -> newState.copy(
      todos = newState.todos.filter
      it.id != action.id
      as MutableList<Todo>
      )



      override fun subscribe(renderer: Renderer<TodoModel>, func: Function<TodoModel, TodoModel>)
      renderer.render(Transformations.map(state, func))









      android kotlin android-listview android-livedata






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Mar 28 at 17:16









      ankuranurag2

      1,3215 silver badges19 bronze badges




      1,3215 silver badges19 bronze badges










      asked Mar 28 at 11:53









      Tomek FalkonTomek Falkon

      142 bronze badges




      142 bronze badges

























          2 Answers
          2






          active

          oldest

          votes


















          1
















          If I understand correctly you need to add a persistence layer to your application.
          Try to use Room Database when load the ListView.
          SavedInstanceState has some limitations and it should not be used to save a large amount of data or complex objects.



          Android Persistence



          Room Database



          Hope this help.






          share|improve this answer
































            0
















            If you need to save the position that the user is in the listView, save only the Int in a bundle on the method onSaveInstanceState() of the fragment. If you want to save the data inside the listView, you do not need to do this, because Android already did that, you just need to put the loadData (your code that init the data and set an adapter to the listView) in onActivityCreated and just restore the position in onViewStateRestored().






            share|improve this answer

























            • Yes, I just want to save the data inside of the listViews. Im sorry, probably because binge-trying to solve this problem for so long I'm still confused. So I did put listOfToDoThings.adapter = TodoAdapter(requireContext(), listOf()) in the onSaveInstanceState() after check if savedInstanceState isn't null. Now, I don't have any way to "loadData". I should retrieve state from TodoStore.kt, right? If so - I have no clue how can I achieve that :(

              – Tomek Falkon
              Mar 28 at 12:50












            • The android save the data to you, when user go away from your app. When they came back, the Android restore the data to you in the adapter. The methods onSave and onRestore, is just to things that Android do not save, like, position in the list, flags of loadState and so on. If the Android kill the app, It will re-create the fragment, so, the data will be loaded from your database again in onActivityCreated.

              – Alex Ferreira
              Mar 28 at 13:06











            • well, i'm not using any database...

              – Tomek Falkon
              Mar 28 at 13:09











            • You will just save the data in memory ? Android will kill your app and the user will lose the todo list. You need to save the data in a file or a database. There are the sharedPreference to use, a file created by you in the SDCard or the sqlite database. Another option is remote server.

              – Alex Ferreira
              Mar 28 at 13:22











            • @OP If you expect the TODO list to survive across quitting the app then restarting the app, then you must use some form of transient storage (saving to disk, for example into a database like Room, etc).

              – EpicPandaForce
              Mar 29 at 1:32













            Your Answer






            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );














            draft saved

            draft discarded
















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55396966%2fsaving-and-restoring-listview-livedata-in-fragments%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            1
















            If I understand correctly you need to add a persistence layer to your application.
            Try to use Room Database when load the ListView.
            SavedInstanceState has some limitations and it should not be used to save a large amount of data or complex objects.



            Android Persistence



            Room Database



            Hope this help.






            share|improve this answer





























              1
















              If I understand correctly you need to add a persistence layer to your application.
              Try to use Room Database when load the ListView.
              SavedInstanceState has some limitations and it should not be used to save a large amount of data or complex objects.



              Android Persistence



              Room Database



              Hope this help.






              share|improve this answer



























                1














                1










                1









                If I understand correctly you need to add a persistence layer to your application.
                Try to use Room Database when load the ListView.
                SavedInstanceState has some limitations and it should not be used to save a large amount of data or complex objects.



                Android Persistence



                Room Database



                Hope this help.






                share|improve this answer













                If I understand correctly you need to add a persistence layer to your application.
                Try to use Room Database when load the ListView.
                SavedInstanceState has some limitations and it should not be used to save a large amount of data or complex objects.



                Android Persistence



                Room Database



                Hope this help.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Mar 28 at 12:38









                TomD88TomD88

                4637 bronze badges




                4637 bronze badges


























                    0
















                    If you need to save the position that the user is in the listView, save only the Int in a bundle on the method onSaveInstanceState() of the fragment. If you want to save the data inside the listView, you do not need to do this, because Android already did that, you just need to put the loadData (your code that init the data and set an adapter to the listView) in onActivityCreated and just restore the position in onViewStateRestored().






                    share|improve this answer

























                    • Yes, I just want to save the data inside of the listViews. Im sorry, probably because binge-trying to solve this problem for so long I'm still confused. So I did put listOfToDoThings.adapter = TodoAdapter(requireContext(), listOf()) in the onSaveInstanceState() after check if savedInstanceState isn't null. Now, I don't have any way to "loadData". I should retrieve state from TodoStore.kt, right? If so - I have no clue how can I achieve that :(

                      – Tomek Falkon
                      Mar 28 at 12:50












                    • The android save the data to you, when user go away from your app. When they came back, the Android restore the data to you in the adapter. The methods onSave and onRestore, is just to things that Android do not save, like, position in the list, flags of loadState and so on. If the Android kill the app, It will re-create the fragment, so, the data will be loaded from your database again in onActivityCreated.

                      – Alex Ferreira
                      Mar 28 at 13:06











                    • well, i'm not using any database...

                      – Tomek Falkon
                      Mar 28 at 13:09











                    • You will just save the data in memory ? Android will kill your app and the user will lose the todo list. You need to save the data in a file or a database. There are the sharedPreference to use, a file created by you in the SDCard or the sqlite database. Another option is remote server.

                      – Alex Ferreira
                      Mar 28 at 13:22











                    • @OP If you expect the TODO list to survive across quitting the app then restarting the app, then you must use some form of transient storage (saving to disk, for example into a database like Room, etc).

                      – EpicPandaForce
                      Mar 29 at 1:32















                    0
















                    If you need to save the position that the user is in the listView, save only the Int in a bundle on the method onSaveInstanceState() of the fragment. If you want to save the data inside the listView, you do not need to do this, because Android already did that, you just need to put the loadData (your code that init the data and set an adapter to the listView) in onActivityCreated and just restore the position in onViewStateRestored().






                    share|improve this answer

























                    • Yes, I just want to save the data inside of the listViews. Im sorry, probably because binge-trying to solve this problem for so long I'm still confused. So I did put listOfToDoThings.adapter = TodoAdapter(requireContext(), listOf()) in the onSaveInstanceState() after check if savedInstanceState isn't null. Now, I don't have any way to "loadData". I should retrieve state from TodoStore.kt, right? If so - I have no clue how can I achieve that :(

                      – Tomek Falkon
                      Mar 28 at 12:50












                    • The android save the data to you, when user go away from your app. When they came back, the Android restore the data to you in the adapter. The methods onSave and onRestore, is just to things that Android do not save, like, position in the list, flags of loadState and so on. If the Android kill the app, It will re-create the fragment, so, the data will be loaded from your database again in onActivityCreated.

                      – Alex Ferreira
                      Mar 28 at 13:06











                    • well, i'm not using any database...

                      – Tomek Falkon
                      Mar 28 at 13:09











                    • You will just save the data in memory ? Android will kill your app and the user will lose the todo list. You need to save the data in a file or a database. There are the sharedPreference to use, a file created by you in the SDCard or the sqlite database. Another option is remote server.

                      – Alex Ferreira
                      Mar 28 at 13:22











                    • @OP If you expect the TODO list to survive across quitting the app then restarting the app, then you must use some form of transient storage (saving to disk, for example into a database like Room, etc).

                      – EpicPandaForce
                      Mar 29 at 1:32













                    0














                    0










                    0









                    If you need to save the position that the user is in the listView, save only the Int in a bundle on the method onSaveInstanceState() of the fragment. If you want to save the data inside the listView, you do not need to do this, because Android already did that, you just need to put the loadData (your code that init the data and set an adapter to the listView) in onActivityCreated and just restore the position in onViewStateRestored().






                    share|improve this answer













                    If you need to save the position that the user is in the listView, save only the Int in a bundle on the method onSaveInstanceState() of the fragment. If you want to save the data inside the listView, you do not need to do this, because Android already did that, you just need to put the loadData (your code that init the data and set an adapter to the listView) in onActivityCreated and just restore the position in onViewStateRestored().







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Mar 28 at 12:21









                    Alex FerreiraAlex Ferreira

                    339 bronze badges




                    339 bronze badges















                    • Yes, I just want to save the data inside of the listViews. Im sorry, probably because binge-trying to solve this problem for so long I'm still confused. So I did put listOfToDoThings.adapter = TodoAdapter(requireContext(), listOf()) in the onSaveInstanceState() after check if savedInstanceState isn't null. Now, I don't have any way to "loadData". I should retrieve state from TodoStore.kt, right? If so - I have no clue how can I achieve that :(

                      – Tomek Falkon
                      Mar 28 at 12:50












                    • The android save the data to you, when user go away from your app. When they came back, the Android restore the data to you in the adapter. The methods onSave and onRestore, is just to things that Android do not save, like, position in the list, flags of loadState and so on. If the Android kill the app, It will re-create the fragment, so, the data will be loaded from your database again in onActivityCreated.

                      – Alex Ferreira
                      Mar 28 at 13:06











                    • well, i'm not using any database...

                      – Tomek Falkon
                      Mar 28 at 13:09











                    • You will just save the data in memory ? Android will kill your app and the user will lose the todo list. You need to save the data in a file or a database. There are the sharedPreference to use, a file created by you in the SDCard or the sqlite database. Another option is remote server.

                      – Alex Ferreira
                      Mar 28 at 13:22











                    • @OP If you expect the TODO list to survive across quitting the app then restarting the app, then you must use some form of transient storage (saving to disk, for example into a database like Room, etc).

                      – EpicPandaForce
                      Mar 29 at 1:32

















                    • Yes, I just want to save the data inside of the listViews. Im sorry, probably because binge-trying to solve this problem for so long I'm still confused. So I did put listOfToDoThings.adapter = TodoAdapter(requireContext(), listOf()) in the onSaveInstanceState() after check if savedInstanceState isn't null. Now, I don't have any way to "loadData". I should retrieve state from TodoStore.kt, right? If so - I have no clue how can I achieve that :(

                      – Tomek Falkon
                      Mar 28 at 12:50












                    • The android save the data to you, when user go away from your app. When they came back, the Android restore the data to you in the adapter. The methods onSave and onRestore, is just to things that Android do not save, like, position in the list, flags of loadState and so on. If the Android kill the app, It will re-create the fragment, so, the data will be loaded from your database again in onActivityCreated.

                      – Alex Ferreira
                      Mar 28 at 13:06











                    • well, i'm not using any database...

                      – Tomek Falkon
                      Mar 28 at 13:09











                    • You will just save the data in memory ? Android will kill your app and the user will lose the todo list. You need to save the data in a file or a database. There are the sharedPreference to use, a file created by you in the SDCard or the sqlite database. Another option is remote server.

                      – Alex Ferreira
                      Mar 28 at 13:22











                    • @OP If you expect the TODO list to survive across quitting the app then restarting the app, then you must use some form of transient storage (saving to disk, for example into a database like Room, etc).

                      – EpicPandaForce
                      Mar 29 at 1:32
















                    Yes, I just want to save the data inside of the listViews. Im sorry, probably because binge-trying to solve this problem for so long I'm still confused. So I did put listOfToDoThings.adapter = TodoAdapter(requireContext(), listOf()) in the onSaveInstanceState() after check if savedInstanceState isn't null. Now, I don't have any way to "loadData". I should retrieve state from TodoStore.kt, right? If so - I have no clue how can I achieve that :(

                    – Tomek Falkon
                    Mar 28 at 12:50






                    Yes, I just want to save the data inside of the listViews. Im sorry, probably because binge-trying to solve this problem for so long I'm still confused. So I did put listOfToDoThings.adapter = TodoAdapter(requireContext(), listOf()) in the onSaveInstanceState() after check if savedInstanceState isn't null. Now, I don't have any way to "loadData". I should retrieve state from TodoStore.kt, right? If so - I have no clue how can I achieve that :(

                    – Tomek Falkon
                    Mar 28 at 12:50














                    The android save the data to you, when user go away from your app. When they came back, the Android restore the data to you in the adapter. The methods onSave and onRestore, is just to things that Android do not save, like, position in the list, flags of loadState and so on. If the Android kill the app, It will re-create the fragment, so, the data will be loaded from your database again in onActivityCreated.

                    – Alex Ferreira
                    Mar 28 at 13:06





                    The android save the data to you, when user go away from your app. When they came back, the Android restore the data to you in the adapter. The methods onSave and onRestore, is just to things that Android do not save, like, position in the list, flags of loadState and so on. If the Android kill the app, It will re-create the fragment, so, the data will be loaded from your database again in onActivityCreated.

                    – Alex Ferreira
                    Mar 28 at 13:06













                    well, i'm not using any database...

                    – Tomek Falkon
                    Mar 28 at 13:09





                    well, i'm not using any database...

                    – Tomek Falkon
                    Mar 28 at 13:09













                    You will just save the data in memory ? Android will kill your app and the user will lose the todo list. You need to save the data in a file or a database. There are the sharedPreference to use, a file created by you in the SDCard or the sqlite database. Another option is remote server.

                    – Alex Ferreira
                    Mar 28 at 13:22





                    You will just save the data in memory ? Android will kill your app and the user will lose the todo list. You need to save the data in a file or a database. There are the sharedPreference to use, a file created by you in the SDCard or the sqlite database. Another option is remote server.

                    – Alex Ferreira
                    Mar 28 at 13:22













                    @OP If you expect the TODO list to survive across quitting the app then restarting the app, then you must use some form of transient storage (saving to disk, for example into a database like Room, etc).

                    – EpicPandaForce
                    Mar 29 at 1:32





                    @OP If you expect the TODO list to survive across quitting the app then restarting the app, then you must use some form of transient storage (saving to disk, for example into a database like Room, etc).

                    – EpicPandaForce
                    Mar 29 at 1:32


















                    draft saved

                    draft discarded















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid


                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.

                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55396966%2fsaving-and-restoring-listview-livedata-in-fragments%23new-answer', 'question_page');

                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Obelisk of Theodosius Contents History Description Notes Bibliography Further reading External links Navigation menuAge of spirituality : late antique and early Christian art, third to seventh centuryOver 60 picturesObelisks of the World41°00′21.24″N 28°58′31.43″E / 41.0059000°N 28.9753972°E / 41.0059000; 28.97539727724550-7235741376235741376

                    밀양 대씨 역사 각주 함께 보기 둘러보기 메뉴밀양 대씨

                    1973년 목차 사건 문화 탄생 사망 노벨상 달력 둘러보기 메뉴