I am developing an app which shows all the installed applications to user with checkboxes. I am succeed in doing so. But I am having problem in saving and retrieving the selected apps by the user. I have used ArrayList for storing selected apps, it works fine but when the app is shutdown all the items in arraylist gets remove. Then I have switched to Storage via SharedPreferences but i didn't work. Last option is to store and retrieve the applicationInfo objects via SQLite database but I dont know how to insert and retrieve an ApplicationInfo object to/from database.
Below is my code(Storage via ArrayList):
main_activity.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
tools:context="com.example.pc.fkidshell.Teen3Activity">
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<Button
android:id="#+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_marginBottom="20dp"
android:text="Add Selected Apps"
android:width="170dp"
android:layout_alignParentBottom="true"
android:layout_gravity="center_horizontal" />
</LinearLayout>
row.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="fill_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/app_icon"
android:layout_width="50dp"
android:layout_height="50dp"
android:padding="3dp"
android:scaleType="centerCrop" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:orientation="vertical"
android:paddingLeft="5dp" >
<TextView
android:id="#+id/app_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textStyle="bold" />
<TextView
android:id="#+id/app_paackage"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical" />
</LinearLayout>
<CheckBox
android:id="#+id/cb_app"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
main_activity.java:
public class Teen3Activity extends ListActivity {
private PackageManager packageManager = null;
private List<ApplicationInfo> applist = null;
private ApplicationAdapter listadaptor = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_teen3);
Button btn1=(Button) findViewById(R.id.btn_add);
btn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
if(MyAddedapss.getAdded_apps().isEmpty())
{
Toast.makeText(getApplicationContext(), "Nothing to ADD!", Toast.LENGTH_LONG).show();
}
else
{
MyAddedapss.writeList(Teen3Activity.this,MyAddedapss.getAdded_apps());
Toast.makeText(getApplicationContext(), "Apps Added!", Toast.LENGTH_LONG).show();
}
}
});
packageManager = getPackageManager();
new LoadApplications().execute();
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id)
{
super.onListItemClick(l, v, position, id);
ApplicationInfo app = applist.get(position);
try {
Intent intent = packageManager.getLaunchIntentForPackage(app.packageName);
if (null != intent) {
startActivity(intent);
}
} catch (ActivityNotFoundException e) {
Toast.makeText(Teen3Activity.this, e.getMessage(), Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(Teen3Activity.this, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
private List<ApplicationInfo> checkForLaunchIntent(List<ApplicationInfo> list)
{
ArrayList<ApplicationInfo> applist = new ArrayList<ApplicationInfo>();
for (ApplicationInfo info : list) {
try {
if (null != packageManager.getLaunchIntentForPackage(info.packageName))
{
applist.add(info);
}
} catch (Exception e)
{
e.printStackTrace();
}
}
return applist;
}
private class LoadApplications extends AsyncTask<Void, Void, Void>
{
private ProgressDialog progress = null;
#Override
protected Void doInBackground(Void... params)
{
applist = checkForLaunchIntent(packageManager.getInstalledApplications(PackageManager.GET_META_DATA));
listadaptor = new ApplicationAdapter(Teen3Activity.this, R.layout.row, applist);
return null;
}
#Override
protected void onCancelled()
{
super.onCancelled();
}
#Override
protected void onPostExecute(Void result)
{
setListAdapter(listadaptor);
progress.dismiss();
super.onPostExecute(result);
}
#Override
protected void onPreExecute()
{
progress = ProgressDialog.show(Teen3Activity.this, null, "Loading application info...");
super.onPreExecute();
}
#Override
protected void onProgressUpdate(Void... values)
{
super.onProgressUpdate(values);
}
}
}
ApplicationAdapter.java:
public class ApplicationAdapter extends ArrayAdapter<ApplicationInfo>
{
private List<ApplicationInfo> appsList = null;
private Context context;
private PackageManager packageManager;
private ArrayList<Boolean> checkList = new ArrayList<Boolean>();
public ApplicationAdapter(Context context, int textViewResourceId, List<ApplicationInfo> appsList)
{
super(context, textViewResourceId, appsList);
this.context = context;
this.appsList = appsList;
packageManager = context.getPackageManager();
for (int i = 0; i < appsList.size(); i++) {
checkList.add(false);
}
}
#Override
public int getCount() {
return ((null != appsList) ? appsList.size() : 0);
}
#Override
public ApplicationInfo getItem(int position) {
return ((null != appsList) ? appsList.get(position) : null);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (null == view) {
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = layoutInflater.inflate(R.layout.row, null);
}
ApplicationInfo data = appsList.get(position);
if (null != data) {
TextView appName = (TextView) view.findViewById(R.id.app_name);
TextView packageName = (TextView) view.findViewById(R.id.app_paackage);
ImageView iconview = (ImageView) view.findViewById(R.id.app_icon);
CheckBox checkBox = (CheckBox) view.findViewById(R.id.cb_app);
checkBox.setTag(Integer.valueOf(position)); // set the tag so we can identify the correct row in the listener
checkBox.setChecked(checkList.get(position));// set the status as we stored it
checkBox.setOnCheckedChangeListener(mListener); // set the listener
appName.setText(data.loadLabel(packageManager));
packageName.setText(data.packageName);
iconview.setImageDrawable(data.loadIcon(packageManager));
}
return view;
}
CompoundButton.OnCheckedChangeListener mListener = new CompoundButton.OnCheckedChangeListener()
{
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
checkList.set((Integer)buttonView.getTag(),isChecked); // get the tag so we know the row and store the status
if(isChecked)
{
int addapppos = (Integer) buttonView.getTag();
ApplicationInfo p=appsList.get(addapppos);
MyAddedapss.setAdded_apps(p);
buttonView.setEnabled(false);
}
}
};
}
MyAddedApps.java: (class for storing the selected Apps by user)
public class MyAddedapss extends Application
{
private static ArrayList<ApplicationInfo> added_apps=new ArrayList<ApplicationInfo>();
public static void setAdded_apps(ApplicationInfo element)
{
added_apps.add(element);
}
public static ArrayList<ApplicationInfo> getAdded_apps()
{
return added_apps;
}
public static boolean remove_app(ApplicationInfo element)
{
return added_apps.remove(element);
}
}
But I am having problem in saving and retrieving the selected apps by the user
Save their package names to a SQLite database, SharedPreferences, or some other form of file (e.g., JSON).
Last option is to store and retrieve the applicationInfo objects via SQLite database but I dont know how to insert and retrieve an ApplicationInfo object to/from database
You can't. You save their package names. Then, on a future run of your app, you load those package names and get the ApplicationInfo objects from Android via PackageManager for those package names.
Related
I am trying to make a musicplayer project in Android Studio. I used RecyclerView to display all the audio files present in the phone with a music icon along with the song's name as an item. The problem is the output on certain devices change in the sense that the recycler view shows empty lists with only the music icon on the screen(that are not playable) and upon scrolling, the audio files present in the phone are displayed in the successive lists with the empty lists still at the top. Why are the empty lists displayed and that too only on some devices?
MainActivity.java
public class MainActivity extends AppCompatActivity implements SongsAdapter.SongsViewHolder.OnSongListener {
List<Songs> songs;
#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() {
#RequiresApi(api = Build.VERSION_CODES.Q)
#Override
public void onPermissionGranted(PermissionGrantedResponse permissionGrantedResponse) {
songs= Songs.getSongs(getApplicationContext());
RecyclerView recyclerView = findViewById(R.id.recyclerView);
SongsAdapter songsAdapter = new SongsAdapter(songs,MainActivity.this,MainActivity.this);
recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));
recyclerView.setAdapter(songsAdapter);
}
#Override
public void onPermissionDenied(PermissionDeniedResponse permissionDeniedResponse) {
android.os.Process.killProcess(android.os.Process.myPid());
}
#Override
public void onPermissionRationaleShouldBeShown(PermissionRequest permissionRequest, PermissionToken permissionToken) {
permissionToken.continuePermissionRequest();
}
})
.check();
}
#Override
public void onSongClick(int position) {
Songs currentSong = songs.get(position);
Intent intent = new Intent(MainActivity.this,PlaySongsActivity.class);
intent.putExtra("SongName",currentSong.getSongName());
intent.putExtra("Uri",currentSong.getUri());
MainActivity.this.startActivity(intent);
}
}
Custom Adapter for recycler view - SongsAdapter.java
public class SongsAdapter extends RecyclerView.Adapter<SongsAdapter.SongsViewHolder>{
private final List<Songs> allSongs;
private SongsViewHolder.OnSongListener mOnSongListener;
Context context;
public SongsAdapter(List<Songs> allSongs, Context context, SongsViewHolder.OnSongListener songListener)
{
this.allSongs = allSongs;
this.context = context;
this.mOnSongListener = songListener;
}
#NonNull
#Override
public SongsViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View listItem = LayoutInflater.from(parent.getContext()).inflate(R.layout.songs_list,parent,false);
return new SongsViewHolder(listItem,mOnSongListener);
}
#Override
public void onBindViewHolder(#NonNull SongsViewHolder holder, int position) {
final Songs currentSong = allSongs.get(position);
holder.audio_image.setImageResource(R.drawable.music_icon);
holder.songName.setText(currentSong.getSongName());
}
#Override
public int getItemCount() {
return allSongs.size();
}
public static class SongsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView songName;
public ImageView audio_image;
OnSongListener onSongListener;
public SongsViewHolder(#NonNull View itemView, OnSongListener onSongListener) {
super(itemView);
this.audio_image = itemView.findViewById(R.id.audio_image);
this.songName = itemView.findViewById(R.id.song_name);
this.onSongListener = onSongListener;
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
onSongListener.onSongClick(getAdapterPosition());
}
public interface OnSongListener
{
void onSongClick(int position);
}
}
}
To retrieve the audios present in the phone - Songs.java
public class Songs {
private final Uri uri;
private final String songName;
public Songs(Uri uri, String songName) {
this.uri = uri;
this.songName = songName;
}
//Method to get all the audio files from the device
#RequiresApi(api = Build.VERSION_CODES.Q)
public static List<Songs> getSongs(Context context) {
List<Songs> songsList = new ArrayList<Songs>();
ContentResolver contentResolver = context.getContentResolver();
Uri externalContentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String[] projection = new String[]{
MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.TITLE,
};
String sortOrder = MediaStore.Video.Media.TITLE + " ASC";
Cursor cursor = contentResolver.query(
externalContentUri, // Uri
projection, // Projection
null, // Selection
null, // Selection args
sortOrder // Sor order
);
if(!cursor.moveToFirst()) //No music files are present
{
//Create an alertDialog
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage(R.string.dialog_message).setTitle(R.string.dialog_title);
builder.setCancelable(false);
builder.setPositiveButton("OK", (dialog, which) -> android.os.Process.killProcess(android.os.Process.myPid()));
AlertDialog alert = builder.create();
alert.show();
}
else
{
int idColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID);
int nameColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE);
while(cursor.moveToNext())
{
long id = cursor.getLong(idColumn);
String song_name = cursor.getString(nameColumn);
Uri contentUri = ContentUris.withAppendedId(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);
songsList.add(new Songs(contentUri, song_name));
}
}
return songsList;
}
public String getSongName() { return this.songName; }
public Uri getUri() {
return this.uri;
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#color/light_azure"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
List Items Layout - songs_list.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:id="#+id/items_layout"
android:padding="16dp">
<ImageView
android:id="#+id/audio_image"
android:layout_width="50dp"
android:layout_height="50dp"
android:contentDescription="audio Icon" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:paddingLeft="16dp">
<TextView
android:id="#+id/song_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/white"
android:textSize="16sp"
android:textStyle="bold"
android:ellipsize="marquee"
android:singleLine="true"
/>
</LinearLayout>
</LinearLayout>
I think that if you try these modifications your lists will display properly, first add this method to your adapter:
public void updateSongs(List<Songs> newSongsList) {
this.allSongs = newSongsList;
this.notifyDataSetChanged();
}
Then in the main activity:
public class MainActivity extends AppCompatActivity implements SongsAdapter.SongsViewHolder.OnSongListener {
List<Songs> songs;
//keep reference to your adapter here, instantiate in onCreate()
SongsAdapter songsAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = findViewById(R.id.recyclerView);
//instantiate adapter with an empty list, update when you have data
songsAdapter = new SongsAdapter(Collections.emptyList(),MainActivity.this,MainActivity.this);
recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));
recyclerView.setAdapter(songsAdapter);
Dexter.withContext(this)
.withPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
.withListener(new PermissionListener() {
#RequiresApi(api = Build.VERSION_CODES.Q)
#Override
public void onPermissionGranted(PermissionGrantedResponse permissionGrantedResponse) {
songs= Songs.getSongs(getApplicationContext());
//now just update your list
songsAdapter.updateSongs(songs);
}
#Override
public void onPermissionDenied(PermissionDeniedResponse permissionDeniedResponse) {
android.os.Process.killProcess(android.os.Process.myPid());
}
#Override
public void onPermissionRationaleShouldBeShown(PermissionRequest permissionRequest, PermissionToken permissionToken) {
permissionToken.continuePermissionRequest();
}
})
.check();
}
#Override
public void onSongClick(int position) {
Songs currentSong = songs.get(position);
Intent intent = new Intent(MainActivity.this,PlaySongsActivity.class);
intent.putExtra("SongName",currentSong.getSongName());
intent.putExtra("Uri",currentSong.getUri());
MainActivity.this.startActivity(intent);
}
}
The code is based by tinder tutorial:
public class arrayadapter extends ArrayAdapter<cards>
{
Context context;
public arrayadapter(Context context, int resource_id, List<cards> items)
{
super(context,resource_id,items);
}
public View getview(int position, View convertview, ViewGroup parent)
{
cards card_item = getItem(position);
if (convertview == null)
{
convertview = LayoutInflater.from(getContext()).inflate(R.layout.item,parent,false);
}
TextView user_name =(TextView) convertview.findViewById(R.id.user_name);
ImageView user_image =(ImageView) convertview.findViewById(R.id.image);
user_name.setText(card_item.getUser_name());
user_image.setImageResource(R.mipmap.ic_launcher); // change in the future with user pic
return convertview;
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="40sp"
android:paddingRight="40sp"
android:paddingTop="20sp"
android:paddingBottom="20sp"
android:outlineProvider="bounds"
android:clipToPadding="false"
>
<androidx.cardview.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:cardCornerRadius="6dp"
android:elevation="2dp"
android:id="#+id/card_view"
>
<FrameLayout
android:layout_gravity="center"
android:layout_width="250dp"
android:layout_height="170dp"
>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/image">
</ImageView>
<TextView
android:id="#+id/user_name"
android:textSize="40sp"
android:textColor="#android:color/black"
android:gravity="center"
tools:text="hello"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
This are the swipe, arrayadapter classes and item xml. The data of the users are not important right now.
public class swipe_cards extends AppCompatActivity {
private cards cards_data[] ;
private arrayadapter arrayadapter;
private int i;
ListView listView;
List<cards>rowitems;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_swipe_cards);
Bundle extras = getIntent().getExtras();
rowitems = new ArrayList<cards>();
//arrayadapter = new arrayadapter (this,R.layout.item,rowitems);
//context,YourCustomLayoutID,TextViewIDinYourLayout,ListData
arrayadapter = new arrayadapter(this,R.layout.item,rowitems);
// ArrayAdapter arrayAdapter = new ArrayAdapter(MainActivity.this,
// R.layout.layout_item_autocomplete, R.id.tvCustom, getResources().getStringArray(R.array.sweets));
SwipeFlingAdapterView flingContainer =(SwipeFlingAdapterView)findViewById(R.id.frame);
flingContainer.setAdapter(arrayadapter);
flingContainer.setFlingListener(new SwipeFlingAdapterView.onFlingListener() {
#Override
public void removeFirstObjectInAdapter() {
// this is the simplest way to delete an object from the Adapter (/AdapterView)
Log.d("LIST", "removed object!");
rowitems.remove(0);
arrayadapter.notifyDataSetChanged();
}
#Override
public void onLeftCardExit(Object dataObject) {
//Do something on the left!
//You also have access to the original object.
//If you want to use it just cast it (String) dataObject
Toast.makeText(swipe_cards.this, "Left!",Toast.LENGTH_SHORT).show();
}
#Override
public void onRightCardExit(Object dataObject) {
Toast.makeText(swipe_cards.this, "Right!",Toast.LENGTH_SHORT).show();
}
#Override
public void onAdapterAboutToEmpty(int itemsInAdapter) {
// Ask for more data here
//rowitems.add("XML ".concat(String.valueOf(i)));
arrayadapter.notifyDataSetChanged();
Log.d("LIST", "notified");
i++;
}
#Override
public void onScroll(float scrollProgressPercent) {
}
});
// Optionally add an OnItemClickListener
flingContainer.setOnItemClickListener(new SwipeFlingAdapterView.OnItemClickListener() {
#Override
public void onItemClicked(int itemPosition, Object dataObject) {
Toast.makeText(swipe_cards.this, "Clicked!",Toast.LENGTH_SHORT).show();
}
});
if (extras != null)
{
ArrayList<String> users= extras.getStringArrayList("potential_users");
for (int counter = 0; counter < users.size(); counter++) {
String user = users.get(counter);
//String[] user_details= user.split(":");
String[] user_details = user.split(",");
String [] name_parmetrs= user_details[0].split(":");
String user_name= name_parmetrs[1];
cards card = new cards("222",user_name);
rowitems.add(card);
arrayadapter.notifyDataSetChanged();
}
}
}
You are creating an array adapter with the contructor where u are just giving 3 parameters- context, layout Id and the row-Items.
So for your constructor with only 3 parameters R.layout.item must be the id of a XML layout file containing only a TextView(the TextView can't be wrapped by another layout, like a LinearLayout, RelativeLayout etc!), something like this:
But in your case, you are using a complex layout So in that case you need to pass both layout id and Textview id in the constructor.
In case u need you don't have textViewId you can pass textViewId as 0.
like this
public arrayadapter(Context context, int resource_id, List<cards> items)
{
super(context,resource_id,0,items);
}
If u have a textview ResourceId you can pass the resourceid in place of 0
public arrayadapter(Context context, int resource_id,int textViewId, List<cards> items)
{
super(context,resource_id,textViewId,items);
}
I have a project in android studio that loads data from an online database and put that data in a listview. Above the listview there is an EditText that i want to search the listview with the value that i write inside. I tried to adapt this tutorial to mine but i get many errors and crashes that i cannot fix becaue i am a noob. Can you help me to adapt the tutorial to my project please? Below is my code without the search filter. If you want i can upload my try with the errors. Thank you in advance!
AllStudents.java:
public class AllStudents extends AppCompatActivity {
ListView StudentListView;
ProgressBar progressBar;
String HttpUrl = "http://sissy-nickels.000webhostapp.com/AllStudentData.php";
List<String> IdList = new ArrayList<>();
String LessonName;
HttpParse httpParse = new HttpParse();
ProgressDialog pDialog;
String FinalJSonObject;
HashMap<String,String> ResultHash = new HashMap<>();
String ParseResult ;
List<Student> studentList;
#Override
public void onBackPressed()
{
super.onBackPressed();
startActivity(new Intent(AllStudents.this, AddStudent.class));
finish();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_allstudents);
StudentListView = (ListView)findViewById(R.id.listview2);
progressBar = (ProgressBar)findViewById(R.id.progressBar);
LessonName = getIntent().getStringExtra("Lesson");
HttpWebCall(LessonName);
//Adding ListView Item click Listener.
StudentListView.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// TODO Auto-generated method stub
Intent intent = new Intent(AllStudents.this,SingleStudent.class);
// Sending ListView clicked value using intent.
intent.putExtra("ListViewValue", IdList.get(position).toString());
startActivity(intent);
//Finishing current activity after open next activity.
finish();
}
});
}
public void HttpWebCall(final String LessonName){
class HttpWebCallFunction extends AsyncTask<String,Void,String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = ProgressDialog.show(AllStudents.this,"Loading Data",null,true,true);
}
#Override
protected void onPostExecute(String httpResponseMsg) {
super.onPostExecute(httpResponseMsg);
pDialog.dismiss();
//Storing Complete JSon Object into String Variable.
FinalJSonObject = httpResponseMsg ;
//Parsing the Stored JSOn String to GetHttpResponse Method.
new GetHttpResponse(AllStudents.this).execute();
}
#Override
protected String doInBackground(String... params) {
ResultHash.put("LessonName",params[0]);
ParseResult = httpParse.postRequest(ResultHash, HttpUrl);
return ParseResult;
}
}
HttpWebCallFunction httpWebCallFunction = new HttpWebCallFunction();
httpWebCallFunction.execute(LessonName);
}
// JSON parse class started from here.
private class GetHttpResponse extends AsyncTask<Void, Void, Void>
{
public Context context;
public GetHttpResponse(Context context)
{
this.context = context;
}
#Override
protected void onPreExecute()
{
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... arg0)
{
try
{
if(FinalJSonObject != null)
{
JSONArray jsonArray = null;
try {
jsonArray = new JSONArray(FinalJSonObject);
JSONObject jsonObject;
Student student;
studentList = new ArrayList<Student>();
for(int i=0; i<jsonArray.length(); i++)
{
jsonObject = jsonArray.getJSONObject(i);
student = new Student();
// Adding Student Id TO IdList Array.
IdList.add(jsonObject.getString("id").toString());
//Adding Student Name.
student.StudentName = jsonObject.getString("Regnum").toString();
studentList.add(student);
}
}
catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result)
{
progressBar.setVisibility(View.GONE);
StudentListView.setVisibility(View.VISIBLE);
ListAdapter adapter = new ListAdapter(studentList, context);
StudentListView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}}
ListAdapter.java
public class ListAdapter extends BaseAdapter {
Context context;
List<Student> valueList=null;
public ListAdapter(List<Student> listValue, Context context)
{
this.context = context;
this.valueList = listValue;
if(valueList==null){
valueList = new ArrayList<>();
}
}
#Override
public int getCount()
{
return this.valueList.size();
}
#Override
public Object getItem(int position)
{
return this.valueList.get(position);
}
#Override
public long getItemId(int position)
{
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewItem viewItem;
convertView = null;
if(convertView == null)
{
viewItem = new ViewItem();
LayoutInflater layoutInfiater = (LayoutInflater)this.context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = layoutInfiater.inflate(R.layout.listviewitem, null);
viewItem.TextViewStudentName = (TextView)convertView.findViewById(R.id.textView1);
convertView.setTag(viewItem);
}
else
{
viewItem = (ViewItem) convertView.getTag();
}
viewItem.TextViewStudentName.setText(valueList.get(position).StudentName);
return convertView;
}}class ViewItem{ TextView TextViewStudentName;}
Student.java:
public class Student {
public String StudentName ;}
listview.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/gradient"
android:padding="15dp">
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:textColor="#android:color/holo_blue_dark"
android:textSize="24dp" />
avtivity_allstudents.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_show_all_students"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.djale.login_register.AllStudents"
android:background="#drawable/gradient"
>
<EditText
android:id="#+id/search"
android:layout_width="250dp"
android:layout_height="30dp"
android:layout_alignParentEnd="true"
android:layout_alignParentStart="true"
android:background="#11000000"
android:ems="10"
android:drawableLeft="#drawable/ic_search_black_24dp"
android:hint=" Search by reg. number"
android:inputType="textPersonName"
android:textColorHint="#android:color/holo_blue_dark"
android:textSize="18sp" />
<ListView
android:id="#+id/listview2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_below="#+id/search" />
<ProgressBar
android:id="#+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="visible"
/>
You can do like this :
search=(EditText)findviewById(R.id.search);
search.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
searchList=new ArrayList<>();
for(studentList name: String){
if(name.toLowerCase().contains(editable.toString().toLowerCase())){
searchList.add(name);
}
}
//clear data in adapter
//add searchList to your adapter
}
});
You can add TextChangedListener to your search box (which is a EditText). In onTextChanged(), filter list & update ListView accordingly.
In AllStudents.java, try making these changes:
public class AllStudents extends AppCompatActivity {
.....
#Override
protected void onCreate(Bundle savedInstanceState) {
....
StudentListView.setOnItemClickListener(...)
// add TextChangedListener to search box.
// It listens for user's entered text & filter students' list by name
EditText searchEditText = (EditText) findViewById(R.id.search);
searchEditText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged (CharSequence s, int start, int count, int after) {
}
// when text is entered in search box, filter list by search text
#Override
public void onTextChanged(CharSequence cs, int start, int before, int count) {
filterStudents(cs);
}
#Override
public void afterTextChanged(Editable s) {
}
});
}
// check student's name whether contain text entered in search box
private void filterStudents (CharSequence cs) {
List<Student> filteredList = new ArrayList<>();
if (TextUtils.isEmpty(cs)) {
// no text is entered for search, do nothing
return;
}
// build new student list which filtered by search text.
for (Student student : studentList) {
if (student.StudentName.contains(cs)) {
filteredList.add(student);
}
}
// show filtered list in listview
ListAdapter adapter = new ListAdapter(filteredList, this);
StudentListView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
I need sort alphabetically in my custom ListView. In list_item, I have TextImage and two TextView (app name, package name) and can't understand how sort by alphabet app name:
My list item:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal">
<ImageView
android:id="#+id/app_icon"
android:layout_width="56dp"
android:layout_height="56dp"
android:padding="4dp"
android:scaleType="centerCrop"
android:contentDescription="#null"
tools:src="#mipmap/ic_launcher" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center|center_vertical"
android:orientation="vertical"
android:paddingLeft="8dp">
<TextView
android:id="#+id/tv_app_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textStyle="bold"
tools:text="Application name"/>
<TextView
android:id="#+id/tv_app_package"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textStyle="bold"
tools:text="app.package.name"/>
</LinearLayout>
</LinearLayout>
And my adapter:
public class ListViewAdapter extends ArrayAdapter{
private Context context;
private List mItem;
private PackageManager packageManager;
public ListViewAdapter(Context context, int list_item, List items) {
super(context, R.layout.list_item, items);
this.context = context;
this.mItem = items;
packageManager = context.getPackageManager();
}
public int getCount(){
return ((null != mItem) ? mItem.size() : 0);
}
#Override
public ApplicationInfo getItem(int position) {
return (null != mItem) ? (ApplicationInfo) mItem.get(position) : null;
}
public long getItemId(int position){
return position;
}
public View getView(int position, View convertView, ViewGroup parent){
View view = convertView;
if (null == view) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.list_item, null);
}
ApplicationInfo data = (ApplicationInfo) mItem.get(position);
if (null != data){
TextView appName = (TextView) view.findViewById(R.id.tv_app_name);
TextView appPackage = (TextView) view.findViewById(R.id.tv_app_package);
ImageView icon = (ImageView) view.findViewById(R.id.app_icon);
appName.setText(data.loadLabel(packageManager));
appPackage.setText(data.packageName);
icon.setImageDrawable(data.loadIcon(packageManager));
}
return view;
}
}
My fragment in which show ListView
public class ResultFragment extends ListFragment {
private PackageManager packageManager = null;
private ListViewAdapter listViewAdapter = null;
private List mItem;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
packageManager = getContext().getPackageManager();
new LoadApplications().execute();
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
ApplicationInfo applicationInfo = (ApplicationInfo) mItem.get(position);
try{
Intent intent = packageManager.getLaunchIntentForPackage(applicationInfo.packageName);
if (intent != null){
startActivity(intent);
}
}catch (ActivityNotFoundException e){
Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show();
}catch (Exception e){
Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show();
}
}
private List<ApplicationInfo> checkForLauncherIntent(List<ApplicationInfo> list){
ArrayList mItem = new ArrayList();
for(ApplicationInfo info : list) {
try{
if(packageManager.getLaunchIntentForPackage(info.packageName) != null) {
mItem.add(info);
}
} catch(Exception e) {
e.printStackTrace();
}
}
return mItem;
}
private class LoadApplications extends AsyncTask<Void, Void, Void>{
private ProgressDialog progressDialog = null;
#Override
protected Void doInBackground(Void... params){
mItem = checkForLauncherIntent(packageManager.getInstalledApplications(PackageManager.GET_META_DATA));
listViewAdapter = new ListViewAdapter(getActivity(), R.layout.list_item, mItem);
return null;
}
#Override
protected void onPostExecute(Void result){
setListAdapter(listViewAdapter);
progressDialog.dismiss();
super.onPostExecute(result);
}
#Override
protected void onPreExecute(){
progressDialog = ProgressDialog.show(getActivity(), null, "Loading file info...");
super.onPreExecute();
}
}
}
Please help me by sorting my list alphabetically.
From Android Documentation
public abstract android.content.Intent
getLaunchIntentForPackage(java.lang.String packageName)
Returns a
"good" intent to launch a front-door activity in a package. This is
used, for example, to implement an "open" button when browsing through
packages. The current implementation looks first for a main activity
in the category Intent.CATEGORY_INFO, and next for a main activity in
the category Intent.CATEGORY_LAUNCHER. Returns null if neither are
found.
Parameters: packageName - The name of the package to inspect.
Returns: A fully-qualified Intent that can be used to launch the main
activity in the package. Returns null if the package does not contain
such an activity, or if packageName is not recognized.
You need to make some changes in your code
private ArrayList<ResolveInfo> checkForLauncherIntent(List<ApplicationInfo> list){
ArrayList<ResolveInfo> mItems = new ArrayList();
for(ApplicationInfo info : list) {
try{
if(packageManager.getLaunchIntentForPackage(info.packageName) != null) {
Intent intent = packageManager.getLaunchIntentForPackage(info.packageName));
ResolveInfo app = packageManager.resolveActivity(intent,0);
mItems.add(app);
}
} catch(Exception e) {
e.printStackTrace();
}
}
return mItems;
}
in your asn task
private class LoadApplications extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params){
ArrayList<ResolveInfo> mItem = checkForLauncherIntent(packageManager.getInstalledApplications(PackageManager.GET_META_DATA));
listViewAdapter = new ListViewAdapter(ctx, mItem);
return null;
}
#Override
protected void onPostExecute(Void result){
super.onPostExecute(result);
listView.setAdapter(listViewAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ResolveInfo resolveInfo = listViewAdapter.getItem(position);
ActivityInfo activityInfo = resolveInfo.activityInfo;
ComponentName name = new ComponentName(activityInfo.applicationInfo.packageName,activityInfo.name);
Intent intent = new Intent();
intent.setComponent(name);
startActivity(intent);
}
});
}
#Override
protected void onPreExecute(){
super.onPreExecute();
//progressDialog = ProgressDialog.show(getActivity(), null, "Loading file info...");
}
}
In your adapter constructor
public class ListViewAdapter extends BaseAdapter {
private Context context;
private ArrayList<ResolveInfo> mItem;
private PackageManager packageManager;
public ListViewAdapter(Context context, ArrayList<ResolveInfo> items) {
this.context = context;
this.mItem = items;
packageManager = context.getPackageManager();
Collections.sort(mItem,new ResolveInfo.DisplayNameComparator(packageManager));
}
public int getCount(){
return mItem.size();
}
#Override
public ResolveInfo getItem(int position) {
return mItem.get(position);
}
public long getItemId(int position){
return position;
}
public View getView(int position, View convertView, ViewGroup parent){
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.testa, null);
}
ResolveInfo app = mItem.get(position);
TextView appName = (TextView) convertView.findViewById(R.id.tv_app_name);
TextView appPackage = (TextView) convertView.findViewById(R.id.tv_app_package);
ImageView icon = (ImageView) convertView.findViewById(R.id.app_icon);
ActivityInfo activity = app.activityInfo;
appPackage.setText(activity.applicationInfo.packageName);
appName.setText(app.loadLabel(packageManager));
icon.setImageDrawable(app.loadIcon(packageManager));
return convertView;
}
}
Find the entire project At Github
First change The Chinese to pinyin you can use the jar pinyin4j-2.5.0.jar
then maybe you can try this method
Arrays.sort(arrayList,String.CASE_INSENSITIVE_ORDER);
Do this it will work
Create a class comparator like this
public class CustomComparator implements Comparator<ApplicationInfo> {
#Override
public int compare(ApplicationInfo o1, ApplicationInfo o2) {
return o1.loadLabel(packageManager).toString().compareTo(o2.loadLabel(packageManager).toString());
}
}
Now use this class in the Async Task where you are creating the adapter
Collections.sort(mItem, new CustomComparator());
listViewAdapter = new ListViewAdapter(context, mItem);
it will sort your list
Let me know in case of more issue
use this method when you need to sort in listview,
Collections.sort(apps, new Comparator<App>() {
#Override
public int compare(App lhs, App rhs) {
//here getTitle() method return app name...
return lhs.getTitle().compareTo(rhs.getTitle());
}
});
Please try this.
public class MainActivity extends AppCompatActivity {
private ArrayList<UserInfo> userInfos;
private CustomListAdapter customListAdapter;
private ListView customListView;
private String[] names={
"3 Khan",
"2 Ahmed",
"1 Iqbal"
};
private String[] professions={
"Rank 1",
"Rank 2",
"Rank 3"
};
private int[] photos={
R.drawable.sample_5,
R.drawable.sample_1,
R.drawable.sample_6
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setSupportActionBar((Toolbar)findViewById(R.id.toolbar));
customListView=(ListView)findViewById(R.id.custom_list_view);
userInfos=new ArrayList<>();
Arrays.sort(names,String.CASE_INSENSITIVE_ORDER);
customListAdapter=new CustomListAdapter(userInfos,this);
customListView.setAdapter(customListAdapter);
getDatas();
customListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(MainActivity.this, "Name : " + names[i] + "\n Profession : " + professions[i], Toast.LENGTH_SHORT).show();
}
});
}
// getting all the datas
private void getDatas(){
for(int count=0;count<names.length;count++){
userInfos.add(new UserInfo(names[count],professions[count],photos[count]));
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.search_option,menu);
MenuItem menuItem=menu.findItem(R.id.search);
SearchView searchView=(SearchView)menuItem.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
newText=newText.toString();
ArrayList<UserInfo> newUserInfos=new ArrayList<>();
for(UserInfo userInfo:userInfos){
String name=userInfo.getName().toLowerCase();
String profession=userInfo.getProfession().toLowerCase();
if(name.contains(newText) || profession.contains(newText)){
newUserInfos.add(userInfo);
}
}
customListAdapter.filterResult(newUserInfos);
customListAdapter.notifyDataSetChanged();
return false;
}
});
return super.onCreateOptionsMenu(menu);
}
}```
Okay, this is how my recyclerview is showing my "posts". Can anyone tell me why? I will post source code as well. I have tried changing some of the code with no success. Also, when I scroll through my RecyclerView, some of them resize to smaller or larger sizes. Any and all help is appreciated!
fragment_home.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff" />
</LinearLayout>
list_item.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="vertical"
android:id="#+id/listItemLayout">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageButton
android:id="#+id/yesButton"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_weight="1"
android:background="#00FF00" />
<ImageButton
android:id="#+id/noButton"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_weight="1"
android:background="#FF0000" />
</LinearLayout>
<com.android.volley.toolbox.NetworkImageView
android:id="#+id/image_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="#drawable/placeholder" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:background="#509f9f9f"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="8"
android:orientation="horizontal">
<com.android.volley.toolbox.NetworkImageView
android:id="#+id/thumbnail"
android:layout_width="40dp"
android:layout_height="40dp"
android:scaleType="fitXY"
android:src="#drawable/placeholder" />
<TextView
android:id="#+id/pUsername"
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="username" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<ImageButton
android:id="#+id/postMenu"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#000"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
LruBitmapCache.java:
public class LruBitmapCache extends LruCache<String, Bitmap> implements ImageCache {
public LruBitmapCache(int maxSize) {
super(maxSize);
}
public LruBitmapCache(Context context) {
this(getCacheSize(context));
}
#Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight();
}
#Override
public Bitmap getBitmap(String url) {
return get(url);
}
#Override
public void putBitmap(String url, Bitmap bitmap) {
put(url, bitmap);
}
public static int getCacheSize(Context context) {
final DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
final int screenWidth = displayMetrics.widthPixels;
final int screenHeight = displayMetrics.heightPixels;
final int screenBytes = screenWidth * screenHeight * 4;
return screenBytes * 3;
}
}
MyRecyclerAdapter.java:
public class MyRecyclerAdapter extends RecyclerView.Adapter<ListRowViewHolder> {
private List<ListItems> listItemsList;
private Context mContext;
private ImageLoader mImageLoader;
private int focusedItem = 0;
public MyRecyclerAdapter(Context context, List<ListItems> listItemsList) {
this.mContext = context;
this.listItemsList = listItemsList;
}
#Override
public ListRowViewHolder onCreateViewHolder(final ViewGroup viewGroup, int position) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item, null);
ListRowViewHolder holder = new ListRowViewHolder(v);
return holder;
}
#Override
public void onBindViewHolder(final ListRowViewHolder listRowViewHolder, int position) {
ListItems listItems = listItemsList.get(position);
listRowViewHolder.itemView.setSelected(focusedItem == position);
listRowViewHolder.getLayoutPosition();
mImageLoader = MySingleton.getInstance(mContext).getImageLoader();
listRowViewHolder.thumbnail.setImageUrl(listItems.getProfilePicture(), mImageLoader);
listRowViewHolder.thumbnail.setDefaultImageResId(R.drawable.placeholder);
listRowViewHolder.image_1.setImageUrl(listItems.getImage_1(), mImageLoader);
listRowViewHolder.image_1.setDefaultImageResId(R.drawable.placeholder);
listRowViewHolder.username.setText(Html.fromHtml(listItems.getUsername()));
}
public void clearAdapter() {
listItemsList.clear();
notifyDataSetChanged();
}
#Override
public int getItemCount() {
return (null != listItemsList ? listItemsList.size() : 0);
}
}
MySingleton.java:
public class MySingleton {
private static MySingleton mInstance;
private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;
private static Context mContext;
private MySingleton(Context context) {
mContext = context;
mRequestQueue = getRequestQueue();
mImageLoader = new ImageLoader(mRequestQueue, new LruBitmapCache(LruBitmapCache.getCacheSize(mContext)));
}
public static synchronized MySingleton getInstance(Context context) {
if (mInstance == null) {
mInstance = new MySingleton(context);
}
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(mContext.getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req) {
getRequestQueue().add(req);
}
public ImageLoader getImageLoader() {
return mImageLoader;
}
}
ListRowViewHolder.java:
public class ListRowViewHolder extends RecyclerView.ViewHolder {
protected NetworkImageView thumbnail;
protected NetworkImageView image_1;
protected ImageButton yes;
protected ImageButton no;
protected TextView username;
protected LinearLayout recLayout;
public ListRowViewHolder(View view) {
super(view);
this.thumbnail = (NetworkImageView) view.findViewById(R.id.thumbnail);
this.image_1 = (NetworkImageView) view.findViewById(R.id.image_1);
this.yes = (ImageButton) view.findViewById(R.id.yesButton);
this.no = (ImageButton) view.findViewById(R.id.noButton);
this.username = (TextView) view.findViewById(R.id.pUsername);
this.recLayout = (LinearLayout) view.findViewById(R.id.listItemLayout);
view.setClickable(true);
}
}
FragmentHome.java:
public class FragmentHome extends Fragment {
private final String postsUrl = "http://www.example.com/fetch_posts.php";
private ProgressDialog progressDialog;
private static final String TAG = "RecyclerViewExample";
private List<ListItems> listItemsList = new ArrayList<>();
private RecyclerView mRecyclerView;
private MyRecyclerAdapter adapter;
public FragmentHome() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (container == null) {
return null;
}
View view = inflater.inflate(R.layout.fragment_home, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
mRecyclerView.addItemDecoration(
new HorizontalDividerItemDecoration.Builder(getActivity())
.color(Color.BLACK)
.build());
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(linearLayoutManager);
updateFeed();
return view;
}
public void updateFeed() {
showPD();
adapter = new MyRecyclerAdapter(getActivity(), listItemsList);
mRecyclerView.setAdapter(adapter);
RequestQueue request = Volley.newRequestQueue(getActivity());
adapter.clearAdapter();
JsonArrayRequest req = new JsonArrayRequest(postsUrl, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
try {
for (int i = 0; i < response.length(); i++) {
JSONObject post = (JSONObject) response.get(i);
ListItems item = new ListItems();
item.setImage_1(post.getString("image_1"));
item.setUsername(post.getString("username"));
item.setProfilePicture(post.getString("image_1"));
listItemsList.add(item);
}
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(getActivity(), "Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
adapter.notifyDataSetChanged();
hidePD();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
hidePD();
Toast.makeText(getActivity(), "Volley Error: " + error.getMessage(), Toast.LENGTH_LONG).show();
}
});
request.add(req);
}
private void showPD() {
if (progressDialog == null) {
progressDialog = new ProgressDialog(getActivity());
progressDialog.setMessage("Loading...");
progressDialog.setCancelable(false);
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.show();
}
}
private void hidePD() {
if (progressDialog != null) {
progressDialog.dismiss();
progressDialog = null;
}
}
#Override
public void onDestroy() {
super.onDestroy();
hidePD();
}
}
Regarding the question "Also, when I scroll through my RecyclerView, some of them resize to smaller or larger sizes." :
As the name says 'Recycler', it reuses the ViewHolder objects. When you scroll down/up and when the view (holder) goes off the screen, the view object wont get destroyed but it will be used again (recycled) to hold/represent another data set that is becoming visible.
If data set at the new position that is becoming visible does not have data (may be null or empty etc) which in your case is profile_pic/thumbnail, the RecyclerView will use the the data of the recycled holder which is used to represent this position. That is why when you have many data sets than that screen can hold and when you scroll up/down, you see that everytime you scroll a view (make it visible and invisible), it will show different data depending on the (recycled)holder it uses at the moment. If your profile pics are different than just cat pic for every view, then you can witness this effect clearly.
What you've to do is that before you set the data (image, text etc) to a view, you can better reset it first. If it is image you can clear/reset as suggested here https://stackoverflow.com/a/8243184/3209739. Or you can have placeholder image or make it transparent whatever. Then this problem should not occur.
I think for same reason, it shows the different sized images (thumb and profile pic).
Try resetting the views before you set to your actual data. Always better to follow this when RecyclerView is used.
Why do you want to have your own caching code ? Why can not you use Picasso image loader, Universal Image Loader or something that suits your requirement. Take a look here to know the different image loaders Picasso v/s Imageloader v/s Fresco vs Glide.
You're not properly inflating your View in onCreateViewHolder() Instead of
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item, null);
you should use
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item, viewGroup, false);
See this answer for more details on the different LayoutInflater.inflate() methods.