阵列适配器在第二个活动中崩溃

Posted

技术标签:

【中文标题】阵列适配器在第二个活动中崩溃【英文标题】:Array Adapter Crashing in Second Activity 【发布时间】:2021-08-27 03:45:06 【问题描述】:

当我在第二个活动中执行 listView.setAdapter(adapter) 时,应用程序崩溃。而如果我在第一个 Activity 中做同样的事情,应用程序就可以正常工作。所有 id 都正确分配给那里的变量。 在第二个活动的列表视图中单击音乐名称后,第三个活动会播放音乐。 现在的问题是为什么我创建了第二个活动来显示列表视图,而我本可以在第一个活动中完成它,所以这就是原因。 在第一个活动中,应用程序从存储中读取数据并从中创建一个数组列表,这需要时间(就像加载歌曲需要 5 秒并且在那段时间没有显示),所以如果我正在播放歌曲活动,我想回到第一个活动,再次从存储中读取数据需要时间,所以我创建了一个更多的活动,只在列表中显示歌曲,所以读取数据只完成一次在第一个活动中,它以数组的形式将数据发送到第二个活动。因此,当我从第三个活动(父活动设置为第二个活动)返回时,我将直接获取列表,因为该数组将在应用程序启动时由第一个活动在第二个活动中初始化。 由于第二个活动不起作用,我还没有添加第二个到第三个活动的意图。但是第三个活动运行良好,因为在我只有两个活动之前,第一个活动加载歌曲并显示列表,第二个活动在正确播放歌曲的位置播放歌曲。现在,自从我将第一个活动分成 2 个以来,我收到了 listview 适配器的此错误

第一个 Activity这里的 listView,我只是为了测试用例创建的,检查字符串数组是否正确,但是第二个 Activity 中的主列表视图我想在哪里显示列表,不起作用,应用程序崩溃,即使一切都一样,显然除了资源 ID。但它不会在此活动中崩溃。


    package com.example.imusic;
    
    import androidx.annotation.NonNull;
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.recyclerview.widget.LinearLayoutManager;
    import androidx.recyclerview.widget.RecyclerView;
    
    import android.Manifest;
    import android.content.Intent;
    import android.os.Bundle;
    import android.os.Environment;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.Adapter;
    import android.widget.AdapterView;
    import android.widget.ArrayAdapter;
    import android.widget.ListView;
    import android.widget.Toast;
    
    import com.karumi.dexter.Dexter;
    import com.karumi.dexter.PermissionToken;
    import com.karumi.dexter.listener.PermissionDeniedResponse;
    import com.karumi.dexter.listener.PermissionGrantedResponse;
    import com.karumi.dexter.listener.PermissionRequest;
    import com.karumi.dexter.listener.single.PermissionListener;
    
    import org.jetbrains.annotations.NotNull;
    
    import java.io.File;
    import java.util.ArrayList;
    
    public class MainActivity extends AppCompatActivity 
    ListView listView;
    //RecyclerView recyclerView;
    ArrayList<File> Song;
        @Override
        protected void onCreate(Bundle savedInstanceState) 
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Dexter.withContext(this)
                    .withPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
                    .withListener(new PermissionListener()
                        @Override
                        public void onPermissionGranted(PermissionGrantedResponse permissionGrantedResponse) 
    //                        Toast.makeText(MainActivity.this, "Persmission Granted", Toast.LENGTH_SHORT).show();
                            Song=fetchSongs(Environment.getExternalStorageDirectory());  //gets external storage directory and passes it to the function which then return list of al songs
                           // Song=fetchSongs(Environment.getExternalStorageDirectory());  //gets external storage directory and passes it to the function which then return list of al songs
                            String []items=new String[Song.size()];//create string arr of size Song
                            for(int i=0;i<Song.size();i++)
                                items[i]=Song.get(i).getName().replace(".mp3","");// put the names of song in array and replaces .mp3 with " "
                            
                            Intent intent=new Intent(MainActivity.this,MainActivity3.class);
                            intent.putExtra("songlist",Song);
                            intent.putExtra("stringlist",items);
                            listView=findViewById(R.id.listView);
    //                        CustomAdapter adapter=new CustomAdapter(MainActivity.this,R.layout.mylayout,items);
    //                        listView.setAdapter(adapter);
                            startActivity(intent);
    //                        Toast.makeText(MainActivity.this, "Successfully created", Toast.LENGTH_SHORT).show();
                        
    
                        @Override
                        public void onPermissionDenied(PermissionDeniedResponse permissionDeniedResponse) 
    //                        Toast.makeText(MainActivity.this, "Persmission Denied", Toast.LENGTH_SHORT).show();
                        
    
                        @Override
                        public void onPermissionRationaleShouldBeShown(PermissionRequest permissionRequest, PermissionToken permissionToken) 
                            permissionToken.continuePermissionRequest();
                        
                    )
                    .check();
        
        public ArrayList<File> fetchSongs(File file)
            ArrayList<File> arrayList=new ArrayList<>();//File array
            File []files =file.listFiles();  //list all the files in files variable from external storage directory
            if(files!=null)//should work only if it is not null
                for(File f: files)//its like for i in files
                    if(!f.isHidden() && f.isDirectory())// if the file is not hidden and present in the directory then only proceeds
                        arrayList.addAll(fetchSongs(f));  //recursive function that return the list of songs
                    
                    else
                        if(f.getName().endsWith(".mp3") && !f.getName().startsWith("."))// check it its a mp3 file
                            arrayList.add(f);//adds mp3 file to array
                        
                    
                
            
            return arrayList; //return the list
        
    

第二次活动 主列表视图在这里,我在这里显示歌曲。 ID 也分配得当


    package com.example.imusic;
    
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.recyclerview.widget.RecyclerView;
    
    import android.Manifest;
    import android.content.Intent;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.ArrayAdapter;
    import android.widget.ListView;
    import android.widget.Toast;
    
    
    import java.io.File;
    import java.util.ArrayList;
    
    public class MainActivity3 extends AppCompatActivity 
        ListView listView;
        ArrayList<File> Song;
        @Override
        protected void onCreate(Bundle savedInstanceState) 
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            listView=findViewById(R.id.listView24);
            Intent intent=getIntent();
            Bundle b=intent.getExtras();
            Toast.makeText(this, "MainActivity3", Toast.LENGTH_SHORT).show();
            Song=(ArrayList) b.getParcelableArrayList("songlist"); // Song=fetchSongs(Environment.getExternalStorageDirectory());  //gets external storage directory and passes it to the function which then return list of al songs
            String []items=new String[Song.size()];//create string arr of size Song
            for(int i=0;i<Song.size();i++)
                items[i]=Song.get(i).getName().replace(".mp3","");// put the names of song in array and replaces .mp3 with " "
            
            String[] itemss=intent.getStringArrayExtra("stringlist");
            int j=0;
            while(j<items.length)
                Log.d("String",items[j]);
                j++;
            
            CustomAdapter adapter=new CustomAdapter(this,R.layout.mylayout,itemss);
            listView.setAdapter(adapter);
        
    

这是我的 CustomAdapter 类

这里我将输入作为字符串数组,然后覆盖了两个方法 getItem() 和 getView() 自定义资源文件中textView的ID为textView2


    package com.example.imusic;
    
    import android.content.Context;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.TextView;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.recyclerview.widget.RecyclerView;
    
    public class CustomAdapter extends ArrayAdapter 
    String [] arr;
    
        public CustomAdapter(@NonNull Context context, int resource, @NonNull String[] objects) 
            super(context, resource, objects);
            int j=0;
    
            this.arr=objects;
            while(j<arr.length)
                Log.d("items",arr[j]);
                j++;
            
        
    
        @Nullable
        @Override
        public String getItem(int position) 
            return arr[position];
        
    
        @NonNull
        @Override
        public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) 
            convertView=LayoutInflater.from(getContext()).inflate(R.layout.mylayout,parent,false);
            TextView t=convertView.findViewById(R.id.textView2);
            t.setText(getItem(position));
            Log.d("items","hello");
            return convertView;
        
    

【问题讨论】:

我发现了错误,实际上是空指针异常。第二个活动中的行 setContentView(R.layout.activity_main);应该是 setContentView(R.layout.activity_main3); ,所以它返回null,对于listview findviewbyid 【参考方案1】:

我认为当你定义适配器时,你会在该行之后添加 adapter.notifydatasetchanged。

【讨论】:

是的,我现在发布了。

以上是关于阵列适配器在第二个活动中崩溃的主要内容,如果未能解决你的问题,请参考以下文章

通过另一个适配器访问一个适配器的数据

我应该如何在两个片段中使用 ViewModel?

需要 Worklight 适配器身份验证

使用intent和get方法时Android应用程序崩溃

Android中的ListView直到我触摸才显示项目

使用firebase将数据回收器适配器传递给其他活动