1

I've been following this guide for RecyclerView and tried to adopt it for my specific usecase, but the RecyclerView is empty when the app is run.

I'm new to Java, and Android development, so I'm just testing things out to try to get a grasp of things. In this particular case I'm just trying to list installed packages where the package name starts with a particular string, like 'com.google' should match 'com.google.camera'.

My main activity looks like this:

public class MainActivity extends AppCompatActivity {

    ArrayList<PackageInfo> packages = new ArrayList<PackageInfo>();
    PackageManager pm;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        RecyclerView lstPackages = (RecyclerView) findViewById(R.id.lstInstalledPackages);

        pm = getPackageManager();
        List<PackageInfo> allPackages = pm.getInstalledPackages(PackageManager.GET_META_DATA);
        for(PackageInfo pkg : allPackages) {
            if(pkg.packageName.startsWith("com.google")){
                packages.add(pkg);
                Log.d("PKG", "Package found: " + pkg.packageName);
            }
        }

        PackageItemAdapter adapter = new PackageItemAdapter(packages);
        lstPackages.setAdapter(adapter);
        lstPackages.setLayoutManager(new LinearLayoutManager(this));
        adapter.notifyDataSetChanged();
    }
}

PackageItem:

public class PackageItem {
    private PackageInfo mPackageInfo;

    public PackageItem(PackageInfo packageInfo) {
        mPackageInfo = packageInfo;
    }

    public String getName() {
        return mPackageInfo.applicationInfo.name;
    }

    public String getPackageId() {
        return mPackageInfo.packageName;
    }

    public String getVersion() {
        return mPackageInfo.versionName;
    }
}

PackageItemAdapter:

public class PackageItemAdapter extends RecyclerView.Adapter<PackageItemAdapter.ViewHolder> {
    public class ViewHolder extends RecyclerView.ViewHolder {
        public TextView packageName;

        public ViewHolder(View viewItem) {
            super(viewItem);

            packageName = (TextView)viewItem.findViewById(R.id.txtPackageName);
        }
    }

    private List<PackageItem> mPackages;

    public PackageItemAdapter(List<PackageInfo> packages) {
        ArrayList<PackageItem> pis = new ArrayList<PackageItem>();
        for(PackageInfo pkg : packages) {
            pis.add(new PackageItem(pkg));
        }
        mPackages = pis;
    }

    @Override
    public PackageItemAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        Context context = parent.getContext();
        LayoutInflater inflater = LayoutInflater.from(context);

        View packageView = inflater.inflate(R.layout.packageitem, parent, false);

        ViewHolder viewHolder = new ViewHolder(packageView);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(PackageItemAdapter.ViewHolder viewHolder, int position) {
        PackageItem packageItem = mPackages.get(position);

        TextView tv = viewHolder.packageName;
        tv.setText(packageItem.getName());
    }

    @Override
    public int getItemCount() {
        return mPackages.size();
    }
}

packageitem.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/txtPackageName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1" />
</LinearLayout>

Can you see anything I've missed, or is there some quirks or something that I had to consider to get this working, or am I totally off?

Izaac Brånn
  • 94
  • 13

3 Answers3

0

I had this problem some time before. You need to set Layout Manager to your recyclerView because without it your Recycler doen't have an appropriate layout and doesn't know how to place your item views inside. So after you find you recycler view:

RecyclerView lstPackages = (RecyclerView) findViewById(R.id.lstInstalledPackages);

add the line with setting layout like

lstPackages.setLayoutManager(new LinearLayoutManager(this));
Eugene V.
  • 90
  • 11
0

You have to apply layoutmanager before you assign adapter to recyclerview. And layoutmanage should contain the orientation for recyclerview.

So replace your this code

 PackageItemAdapter adapter = new PackageItemAdapter(packages);
    lstPackages.setAdapter(adapter);
    lstPackages.setLayoutManager(new LinearLayoutManager(this));
    adapter.notifyDataSetChanged();

With this

      PackageItemAdapter adapter = new PackageItemAdapter(packages);
    //set layout manager before you set adaptor. 
    lstPackages.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));
    // then assign adapter to your recyclerview 
    lstPackages.setAdapter(adapter);
    //comment this line bcoz you dont need
   // adapter.notifyDataSetChanged();
Rahul sharma
  • 1,492
  • 12
  • 26
-1

So, after messing around and checking things over and over again, I found out that the issue was that return mPackageInfo.applicationInfo.name; in the PackageItem class doesn't return the app name, as anyone might think. Found some info here about that, specifically this answer.

I had to make some changes so that I pass the PackageManager along so that it can get the actual app name.

MainActivity changes:

PackageItemAdapter adapter = new PackageItemAdapter(packages, pm);

PackageItemAdater changes:

public PackageItemAdapter(List<PackageInfo> packages, PackageManager pm) {
   ArrayList<PackageItem> pis = new ArrayList<>();
   for(PackageInfo pkg : packages) {
       pis.add(new PackageItem(pkg, pkg.applicationInfo.loadLabel(pm).toString()));
   }
   mPackages = pis;
}

PackageItem changes:

public class PackageItem {
    private PackageInfo mPackageInfo;
    private String mName;

    public PackageItem(PackageInfo packageInfo, String name) {
        mPackageInfo = packageInfo;
        mName = name;
    }

    public String getName() {
        return mName;
    }
}
Izaac Brånn
  • 94
  • 13