简体   繁体   English

从ViewPager活动刷新片段中的ListView崩溃

[英]Refreshing ListView in a fragment from ViewPager activity crashes

I have an Activity with a ViewPager with 2 fragments inside it. 我有一个带有ViewPager的Activity,其中有2个片段。 One fragment is for adding items to ListView and the other fragment contains the ListView. 一个片段用于向ListView添加项目,另一个片段包含ListView。 Right now I have to restart the app to refresh the ListView once the items are added but I am trying to fix that. 现在,一旦添加了项目,我必须重新启动应用程序以刷新ListView,但我正在尝试修复该问题。 Here's how: 这是如何做:

I'm trying to call the method to refresh ListView from ViewPager like this: 我试图像下面这样调用从ViewPager刷新ListView的方法:

@Override
public void onPageSelected(int position) {
    library.populateListView(getApplicationContext(), library.lView); //this is line 47
    aBar.setSelectedNavigationItem(position);
}

This is the populateListView method inside library fragment: 这是片段中的populateListView方法:

public void populateListView(Context context, ListView listView){   
    CustomListViewAdapter customAdapter = new CustomListViewAdapter(getDatabaseArrayList(context), getActivity());  
    listView.setAdapter(customAdapter); //this is line 122
    customAdapter.notifyDataSetChanged();
}

And the getDatabaseArrayList method code: 以及getDatabaseArrayList方法代码:

private ArrayList<RecordDetails> getDatabaseArrayList(Context context){
    DatabaseHandler dbHandler = new DatabaseHandler(context);
    Cursor c = dbHandler.getAllRecordedFiles();
    ArrayList<RecordDetails> components = new ArrayList<RecordDetails>();
    RecordDetails element;
    if(c.moveToFirst()){
        element = new RecordDetails();
        element.setTitle(c.getString(c.getColumnIndex(SQLiteHelper.MUSIC_NAME)));
        element.setDate(c.getString(c.getColumnIndex(SQLiteHelper.MUSIC_DATE)));
        element.setDuration(c.getString(c.getColumnIndex(SQLiteHelper.MUSIC_DURATION)));
        components.add(element);

        while (c.moveToNext())
        {
            element = new RecordDetails();
            element.setTitle(c.getString(c.getColumnIndex(SQLiteHelper.MUSIC_NAME)));
            element.setDate(c.getString(c.getColumnIndex(SQLiteHelper.MUSIC_DATE)));
            element.setDuration(c.getString(c.getColumnIndex(SQLiteHelper.MUSIC_DURATION)));
            components.add(element);
        }
    }
    return components;
}

My guess is that the application is crashing because I'm calling ListView from ViewPager activity like library.lView which probably returns null . 我的猜测是应用程序崩溃了,因为我是从ViewPager活动(如library.lView)调用ListView,它可能返回null But how do I fix that? 但是我该如何解决呢? I tried to declare a new ListView variable inside the ViewPager activity but it crashed probably because the activity doesn't include the ListView itself. 我试图在ViewPager活动中声明一个新的ListView变量,但是它崩溃了,可能是因为该活动不包括ListView本身。

Here's the logcat output if it helps: 如果有帮助,这是logcat的输出:

03-04 08:43:44.092: E/AndroidRuntime(1779): FATAL EXCEPTION: main
03-04 08:43:44.092: E/AndroidRuntime(1779): java.lang.NullPointerException
03-04 08:43:44.092: E/AndroidRuntime(1779):     at com.matejhacin.beautifulvoicerecorder.LibraryFragment.populateListView(LibraryFragment.java:124)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at com.matejhacin.beautifulvoicerecorder.MainActivity$1.onPageSelected(MainActivity.java:46)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.support.v4.view.ViewPager.scrollToItem(ViewPager.java:567)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:551)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.support.v4.view.ViewPager.onTouchEvent(ViewPager.java:2015)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.View.dispatchTouchEvent(View.java:7384)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2205)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1940)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2211)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1954)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2211)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1954)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2211)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1954)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1966)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1418)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.app.Activity.dispatchTouchEvent(Activity.java:2424)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1914)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.View.dispatchPointerEvent(View.java:7564)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:3883)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3778)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3379)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3429)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3398)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3483)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3406)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3540)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3379)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3429)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3398)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3406)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3379)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5419)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5399)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5370)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5493)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:182)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.os.MessageQueue.nativePollOnce(Native Method)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.os.MessageQueue.next(MessageQueue.java:132)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.os.Looper.loop(Looper.java:124)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at android.app.ActivityThread.main(ActivityThread.java:5103)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at java.lang.reflect.Method.invokeNative(Native Method)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at java.lang.reflect.Method.invoke(Method.java:525)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
03-04 08:43:44.092: E/AndroidRuntime(1779):     at dalvik.system.NativeStart.main(Native Method)

Let me know if I need to post the full logcat because I only posted the part I find the most important. 让我知道是否需要发布完整的日志,因为我只发布了我认为最重要的部分。

UPDATE------------------------------ 更新------------------------------

Full onCreateView code: 完整的onCreateView代码:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_library, container, false);

    // ListView
    lView = (ListView) v.findViewById(R.id.listView);
    lView.setOnItemClickListener(this);
    registerForContextMenu(lView);

    //Other variables
    components = new ArrayList<RecordDetails>();
    components = getDatabaseArrayList(getActivity());
    db = new DatabaseHandler(getActivity());
    mp = new MediaPlayer();
    playPause = (Button) v.findViewById(R.id.playPause);
    playPause.setOnClickListener(this);
    sBar = (SeekBar) v.findViewById(R.id.seekBar1);
    sBar.setOnSeekBarChangeListener(this);
    seekHandler = new Handler();

    populateListView(getActivity());
    seekHandler.post(run);

    return v;
}

UPDATE 2--------------- 更新2 ---------------

Library Fragment XML code: 库片段XML代码:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/gradient_background"
tools:context=".LibraryFragment" >

<ListView
    android:id="@+id/listView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_above="@+id/seekBar1"
    android:layout_below="@+id/view1"
    android:layout_centerHorizontal="true"
    android:focusable="false"
    android:focusableInTouchMode="false" >

</ListView>

<View
    android:id="@+id/view1"
    android:layout_width="wrap_content"
    android:layout_height="40dp"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:background="@drawable/gradient_shadow_transparent" />

<SeekBar
    android:id="@+id/seekBar1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_marginBottom="53dp"
    android:layout_marginLeft="40dp"
    android:layout_marginRight="40dp" />

<Button
    android:id="@+id/playPause"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:text="Play" />

<TextView
    android:id="@+id/current"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignBottom="@+id/seekBar1"
    android:layout_alignParentLeft="true"
    android:text="0:03"
    android:layout_marginLeft="5dp" />

<TextView
    android:id="@+id/duration"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignBottom="@+id/seekBar1"
    android:layout_alignParentRight="true"
    android:text="0:17"
    android:layout_marginRight="5dp" />

I think you dont need to send the listview from ViewPagerActivity. 我认为您不需要从ViewPagerActivity发送listview。 Keep instance of listview in your library fragment itself, store it in onCreateView. 将listview实例保留在您的库片段本身中,并将其存储在onCreateView中。

Change your populateListView to 将您的populateListView更改为

public void populateListView(Context context){   
    CustomListViewAdapter customAdapter = new CustomListViewAdapter(getDatabaseArrayList(context), getActivity());  
    lView.setAdapter(customAdapter); //this is line 122
    customAdapter.notifyDataSetChanged();
}

If this code is in fragment then you need to change from 如果这段代码是片段,那么您需要从

@Override
public void onPageSelected(int position) {
 library.populateListView(getApplicationContext(), library.lView); //this is line 47
 aBar.setSelectedNavigationItem(position);
}

to

@Override
public void onPageSelected(int position) {
 library.populateListView(getActivity(), library.lView); //this is line 47
 aBar.setSelectedNavigationItem(position);
}

you have to also change here because in your populateListView there is two parameters and while you are executing only with Context. 您还必须在此处进行更改,因为在populateListView中有两个参数,并且仅在使用Context执行时。 So change it. 所以改变它。

  populateListView(getActivity());

to

  populateListView(getActivity() , lv);

I think problem might be here 我认为问题可能在这里

   components = getDatabaseArrayList(getActivity());
   db = new DatabaseHandler(getActivity());

getDatabaseArrayList is your function which is executing and after that you have initialize your Database class. getDatabaseArrayList是正在执行的函数,然后初始化数据库类。 So it will be crashed here. 因此它将在这里崩溃。 So change 所以改变

   db = new DatabaseHandler(getActivity());
   components = getDatabaseArrayList(getActivity());

Have you tried with this?? 你尝试过这个吗?

  public void populateListView(Context context){   
   CustomListViewAdapter customAdapter = new CustomListViewAdapter(components, getActivity());  
   lView.setAdapter(customAdapter); //this is line 122
   customAdapter.notifyDataSetChanged();
  }

From what I understood from your code is that you are trying to refresh the listView with the new data and this leads your app to be crashed. 据我从您的代码中了解到,您正在尝试使用新数据刷新listView ,这会使您的应用程序崩溃。

To refresh your listview safely you need to create a method in your customAdapter called setNewData(ArrayList<object> newData) . 为了安全地刷新listview ,您需要在customAdapter创建一个名为setNewData(ArrayList<object> newData) Replace the object with the data type you are using and in this method do the following: 用您正在使用的数据类型替换object ,然后在此方法中执行以下操作:

public void setNewDAta(ArrayList<object> newData){
    this.data = newData;
}

And from you main activity make the customAdapter a global vairable by declaring it in the start of your activity to ensure that you are using only one and create a method to pass the new data to the adapter and refresh it as following: 在您的主要活动中,通过在活动开始时对其进行声明,以使customAdapter成为全局变量,以确保您仅使用一个adapter ,并创建一种将新数据传递给adapter并刷新它的方法,如下所示:

public void setListViewData(ArrayList<object> newData){
    customAdapter.setNewDAta(newData);
    customAdapter.notifyDataSetChanged();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM