I'm trying to modify an application to use the getShortClassName() method instead of displaying the full class name (e.g. "com.google.app.MainActivity" to simply ".MainActivity"). The current setup gives me no errors but doesn't display the text.
I presume the solution is not complicated, although I just don't have the experience to make it work. Help?
#Override
public View getChildView (int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
MyActivityInfo activity = (MyActivityInfo)getChild(groupPosition, childPosition);
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.all_activities_child_item, null);
TextView text1 = (TextView) view.findViewById(android.R.id.text1);
text1.setText(activity.getName());
//TextView text2 = (TextView) view.findViewById(android.R.id.text2);
//text2.setText(activity.getComponentName().getClassName());
TextView text2 = (TextView) view.findViewById(android.R.id.text2);
text2.setText(activity.getShortClassName());
ImageView icon = (ImageView) view.findViewById(android.R.id.icon);
icon.setImageDrawable(activity.getIcon());
return view;
}
public class MyActivityInfo implements Comparable<MyActivityInfo> {
public MyActivityInfo(ComponentName activity, PackageManager pm) {
this.component_name = activity;
ActivityInfo act;
try {
act = pm.getActivityInfo(activity, 0);
this.name = act.loadLabel(pm).toString();
try {
this.icon = (BitmapDrawable)act.loadIcon(pm);
}
catch(ClassCastException e) {
this.icon = (BitmapDrawable)pm.getDefaultActivityIcon();
}
this.icon_resource = act.getIconResource();
} catch (NameNotFoundException e) {
this.name = activity.getShortClassName();
this.icon = (BitmapDrawable)pm.getDefaultActivityIcon();
this.icon_resource = 0;
}
this.icon_resource_name = null;
if(this.icon_resource != 0) {
try {
this.icon_resource_name = pm.getResourcesForActivity(activity).getResourceName(this.icon_resource);
} catch (Exception e) {}
}
}
public ComponentName getComponentName() {
return component_name;
}
public BitmapDrawable getIcon() {
return icon;
}
public String getName() {
return name;
}
public String getIconResourceName() {
return icon_resource_name;
}
public String getShortClassName() {
return class_name;
}
protected ComponentName component_name;
protected BitmapDrawable icon;
protected int icon_resource;
protected String icon_resource_name;
protected String name;
protected String class_name;
#Override
public int compareTo(MyActivityInfo another) {
int cmp_name = this.name.compareTo(another.name);
if (cmp_name != 0) return cmp_name;
int cmp_component = this.component_name.compareTo(another.component_name);
return cmp_component;
}
#Override
public boolean equals(Object other) {
if(!other.getClass().equals(MyPackageInfo.class)) {
return false;
}
MyActivityInfo other_info = (MyActivityInfo)other;
return this.component_name.equals(other_info.component_name);
}
}
You could just use getSimpleName() method of class object:
String a = "Hello";
System.out.println(a.getClass().getSimpleName());
System.out.println(a.getClass().getName());
Output:
String
java.lang.String
Related
When I try to take all the values of the NumberPicker, it correctly returns the ones in the middle, while the first and last returns only the last one that has been modified between them. I don't understand where I'm wrong.
public class piatto {
String nome;
String Descrizione;
String prezzo;
String immagine;
String tag;
public piatto(String nome, String Descrizione, String prezzo, String immagine, String tag) {
this.nome= nome;
this.Descrizione= Descrizione;
this.prezzo= prezzo;
this.immagine=immagine;
this.tag=tag;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getDescrizione() {
return Descrizione;
}
public void setDescrizione(String descrizione) {
Descrizione = descrizione;
}
public String getPrezzo() {
return prezzo;
}
public void setPrezzo(String prezzo) {
this.prezzo = prezzo;
}
public String getImmagine() {
return immagine;
}
public void setImmagine(String immagine) {
this.immagine = immagine;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
}
this is my adapeter
public class ProductListAdapterforListView extends BaseAdapter {
private Context mContext;
private List<piatto> mProductList;
public ProductListAdapterforListView(Context mContext, List<piatto> mProductList) {
this.mContext = mContext;
this.mProductList = mProductList;
}
#Override
public int getCount() {
return mProductList.size();
}
#Override
public piatto getItem(int position) {
return mProductList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View listitemview ;
if (convertView==null){
listitemview = View.inflate(mContext, R.layout.row_data_list, null);
ImageView i = (ImageView) listitemview.findViewById(R.id.imagepiatto);
com.shawnlin.numberpicker.NumberPicker numberPicker = (com.shawnlin.numberpicker.NumberPicker) listitemview.findViewById(R.id.number_picker);
TextView n=(TextView) listitemview.findViewById(R.id.namepiatto);
TextView p=(TextView) listitemview.findViewById(R.id.prezzopiatto);
n.setText(mProductList.get(position).getNome());
p.setText(mProductList.get(position).getPrezzo()+" €");
Picasso.get().load(mProductList.get(position).getImmagine()).into(i);
} else {
listitemview=convertView;
}
return listitemview;
}
}
And this is my Java class where I get the values of the NumberPicker of each Item
#Override
public void onClick(View view) {
if (view.getId()==R.id.buttonnext){
Float totale = (float) 0.0;
String listapiatti="";
for (int i = 0; i < listView.getChildCount(); i++) {
view = listView.getChildAt(i);
TextView n = view.findViewById(R.id.namepiatto);
String nome = n.getText().toString();
TextView p = view.findViewById(R.id.prezzopiatto);
String pricestr = p.getText().toString();
String[] prezzo = pricestr.split(" ");
Float price = Float.valueOf(prezzo[0]);
com.shawnlin.numberpicker.NumberPicker numberPicker = (com.shawnlin.numberpicker.NumberPicker) view.findViewById(R.id.number_picker);
int value = numberPicker.getValue();
if (value != 0) {
totale = totale + (price * value);
listapiatti = listapiatti + nome + ": " + value + ", ";
Toast.makeText(getApplicationContext(), String.valueOf(i)+" "+value,
Toast.LENGTH_LONG).show();
}
}
String finale=String.valueOf(totale);
startActivity(new Intent(carrello3.this, ordine.class));
}
if (view.getId()==R.id.buttonback){
onBackPressed();
}
}
it doesn't seem like a good idea to create an object on setOnScrollListener which gets called many many times during scrolling up/down. if you could provide more detail would be great.
guys.
I'm totally new to programming and Android programming and I have a problem. I fetch images from MySQL database as InputStream. Then I have Adapter where I load data, that I got from database, to corresponding objects. Hooray, listView is created and everything looks good! But... When I scroll down/up my images dissapear. I've read that listView recycles objects, but the problem is that I don't know/understand how can I fix this problem :///
Please help me guys !!
SHORT: images dissapear in listView on scroll. Too much newbie to understand how to fix it :/
Event class
public class Event {
private int id;
private String title;
private Date date;
private String place;
private String genre;
private String description;
private Double price;
public Event(int id, String title, Date date, String place, String genre, String description, Double price, InputStream image) {
this.id = id;
this.title = title;
this.date = date;
this.place = place;
this.genre = genre;
this.description = description;
this.price = price;
this.image = image;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getPlace() {
return place;
}
public void setPlace(String place) {
this.place = place;
}
public String getGenre() {
return genre;
}
public void setGenre(String genre) {
this.genre = genre;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public InputStream getImage() {
return image;
}
public void setImage(InputStream image) {
this.image = image;
}
private InputStream image;
}
Adapter Class
public class EventAdapter extends BaseAdapter {
LayoutInflater mInflater;
ArrayList<Event> data;
public EventAdapter(Context c, ArrayList<Event> d){
mInflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.data = d;
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
// This is where data is assigned to coresponding fields in event_layout
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Hooks
View view = mInflater.inflate(R.layout.event_layout, null);
TextView eventName = (TextView) view.findViewById(R.id.eventName);
TextView dateYear = (TextView) view.findViewById(R.id.dateYear);
TextView dateDay = (TextView) view.findViewById(R.id.dateDay);
ImageView image = (ImageView) view.findViewById(R.id.eventImage);
// Changing date format
SimpleDateFormat sdf = new SimpleDateFormat("MMM dd yyyy");
String date = sdf.format(data.get(position).getDate());
// Extracting date into seprate vars
String year = date.substring(8);
String day = date.substring(0, 1).toUpperCase() + date.substring(1, 3) + "." + date.substring(4, 7) + "d.";
// making Bitmap from InputStream
Bitmap bmp = BitmapFactory.decodeStream(data.get(position).getImage());
eventName.setText(data.get(position).getTitle());
dateYear.setText(year);
dateDay.setText(day);
image.setImageBitmap(bmp);
return view;
}
}
EventsPage class
public class EventsPage extends AppCompatActivity {
private EventAdapter eventAdapter;
private Context thisContext;
private ListView eventsListView;
private TextView progressBar;
private ArrayList<Event> events = new ArrayList<Event>();
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
protected void onCreate(Bundle savedInstanceState) {
// Set status bar color to main_green
if(Build.VERSION.SDK_INT >= 21){
Window window = this.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
window.setStatusBarColor(this.getResources().getColor(R.color.main_green_color , this.getTheme()));
}
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_events_page);
Resources res = getResources();
eventsListView = (ListView) findViewById(R.id.eventsListView);
progressBar = (TextView) findViewById(R.id.progressBar);
thisContext = this;
progressBar.setText("");
GetData data = new GetData();
data.execute("");
}
public class GetData extends AsyncTask<String, String, String> {
private String msg;
private ArrayList<Event> bkc_events = new ArrayList<>();
private ArrayList<Event> tic_events = new ArrayList<>();
#Override
protected void onPreExecute(){
progressBar.setText("Connecting to database...");
}
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
protected String doInBackground(String... strings) {
Connection conn = null;
Statement stmt = null;
try {
Class.forName(DBstrings.JDBC_DRIVER);
conn = DriverManager.getConnection(DBstrings.URL, DBstrings.USERNAME, DBstrings.PASSWORD);
// Get BKC events
stmt = conn.createStatement();
String query = "SELECT * from `bkc_event` ORDER by `date` ASC";
ResultSet res = stmt.executeQuery(query);
while(res.next()){
Event temp = new Event(res.getInt("ID"), res.getString("title"),
res.getDate("date"), res.getString("place"),
res.getString("genre"), res.getString("description"),
res.getDouble("price"), res.getBinaryStream("image"));
this.bkc_events.add(temp);
}
res.close();
// Get TIC events
query = "SELECT * from `tic_event` ORDER by `date` ASC";
res = stmt.executeQuery(query);
while(res.next()){
Event temp = new Event(res.getInt("ID"), res.getString("title"),
res.getDate("date"), res.getString("place"),
res.getString("genre"), res.getString("description"),
res.getDouble("price"), res.getBinaryStream("image"));
tic_events.add(temp);
}
res.close();
stmt.close();
conn.close();
msg = "Process Completed";
PutDataTogether(bkc_events, tic_events);
} catch (ClassNotFoundException ex) {
msg = "Class not found ERROR";
Log.e("ClassNotFound", ex.getMessage());
} catch (SQLException ex) {
msg = "SQL exceltion";
Log.e("SQL:", ex.getMessage());
} finally {
try {
if(stmt != null)
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return null;
}
// Combine data 2 sets into 1 set
#RequiresApi(api = Build.VERSION_CODES.N)
private void PutDataTogether(ArrayList<Event> bkc, ArrayList<Event> tic){
events.addAll(bkc);
for (Event t: tic) {
// counter for showing redundancy
int counter = 0;
for(Event r: events){
// Check if title and date is the same if so - increase counter by 1
if(t.getTitle().toLowerCase().equals(r.getTitle().toLowerCase()) &&
t.getDate().equals(r.getDate()))
counter++;
}
// if counter == 0, then we can add event to final result set
if(counter == 0)
events.add(t);
}
events.sort(Comparator.comparing(Event::getDate));
}
// To show the data
#Override
protected void onPostExecute(String msg){
progressBar.setText(this.msg);
/*new Handler().postDelayed(new Runnable() {
#Override
public void run() {
progressBar.setVisibility(View.INVISIBLE);
}
}, 1500); */
// We have stuff to display
if(events.size() > 0){
eventAdapter = new EventAdapter(thisContext, events);
eventsListView.setAdapter(eventAdapter);
}
}
} // END of GetDataEvents class
} // END of EventsPage
The problem:
Picture before scrolling
Picture after scrolling down and then back up
The issue is within the getView() method of your adapter. Recycling in a ListView means, that there is already an existing View which will be used to display your values, so you must not inflate a new one. Change your code like:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Hooks
View view = convertView;
if (view == null) {
view = mInflater.inflate(R.layout.event_layout, null);
}
TextView eventName = (TextView) view.findViewById(R.id.eventName);
TextView dateYear = (TextView) view.findViewById(R.id.dateYear);
TextView dateDay = (TextView) view.findViewById(R.id.dateDay);
ImageView image = (ImageView) view.findViewById(R.id.eventImage);
// Changing date format
SimpleDateFormat sdf = new SimpleDateFormat("MMM dd yyyy");
String date = sdf.format(data.get(position).getDate());
// Extracting date into seprate vars
String year = date.substring(8);
String day = date.substring(0, 1).toUpperCase() + date.substring(1, 3) + "." + date.substring(4, 7) + "d.";
// making Bitmap from InputStream
Bitmap bmp = BitmapFactory.decodeStream(data.get(position).getImage());
eventName.setText(data.get(position).getTitle());
dateYear.setText(year);
dateDay.setText(day);
image.setImageBitmap(bmp);
return view;
}
Note I only changed the first 4 lines of the method to use the provided View which comes from the ListView and only inflate a new one when there is no existing to reuse.
I trying to add admob native ads in recyclerview that uses resourcecursoradapter adapter .. the issues is
1 - it makes app crash
2 - it replaces recyclerview data item with admob ads
that is my code
public class EntriesCursorAdapter extends ResourceCursorAdapter {
private final Uri mUri;
private final boolean mShowFeedInfo;
private int mIdPos, mTitlePos, mMainImgPos, mDatePos, mIsReadPos, mFavoritePos, mFeedIdPos, mFeedNamePos;
public static final int Ads_view_type = 11;
public EntriesCursorAdapter(Context context, Uri uri, Cursor cursor, boolean showFeedInfo) {
super(context, PrefUtils.getInt(PrefUtils.NEWS_FORMAT_int,R.layout.item_entry_list2), cursor, 0);
mUri = uri;
mShowFeedInfo = showFeedInfo;
reinit(cursor);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
final int position = cursor.getPosition();
final int viewtype = getItemViewType(position);
View itemView ;
if(viewtype == Ads_view_type) {
final LayoutInflater inflater = LayoutInflater.from(context);
itemView = inflater.inflate(R.layout.native_ads, parent, false);
if (itemView.getTag(R.id.holder) == null) {
AdsHolder ads_holder = new AdsHolder();
ads_holder.adView = (NativeExpressAdView) itemView.findViewById(R.id.adView2);
itemView.setTag(R.id.holder, ads_holder);
} return itemView;
}
else {
final LayoutInflater inflater = LayoutInflater.from(context);
itemView = inflater.inflate(PrefUtils.getInt(PrefUtils.NEWS_FORMAT_int, R.layout.item_entry_list2), parent, false);
if (itemView.getTag(R.id.holder) == null) {
ViewHolder holder = new ViewHolder();
holder.titleTextView = (TextView) itemView.findViewById(android.R.id.text1);
holder.dateTextView = (TextView) itemView.findViewById(android.R.id.text2);
holder.mainImgView = (ImageView) itemView.findViewById(R.id.main_icon);
holder.starImgView = (ImageView) itemView.findViewById(R.id.favorite_icon);
itemView.setTag(R.id.holder, holder);
}
return itemView;
}
}
#Override
public int getItemViewType(int position) {
if(position % 6 ==0)
{return Ads_view_type;}
else {
return super.getItemViewType(position);
}
}
#Override
public void bindView(View view, final Context context, Cursor cursor) {
final int position = cursor.getPosition();
final int viewtype = getItemViewType(position);
if (viewtype == Ads_view_type) {
try {
AdsHolder adsHolder = (AdsHolder) view.getTag(R.id.holder);
AdRequest request = new AdRequest.Builder()
.addTestDevice("ca-app-pub-5647351014779121/8591922893")
.build();
adsHolder.adView.loadAd(request);
} catch (Exception e) {
}
} else {
try {
ViewHolder holder = (ViewHolder) view.getTag(R.id.holder);
String titleText = cursor.getString(mTitlePos);
holder.titleTextView.setText(titleText);
final long feedId = cursor.getLong(mFeedIdPos);
String feedName = cursor.getString(mFeedNamePos);
String mainImgUrl = cursor.getString(mMainImgPos);
mainImgUrl = TextUtils.isEmpty(mainImgUrl) ? null : NetworkUtils.getDownloadedOrDistantImageUrl(cursor.getLong(mIdPos), mainImgUrl);
ColorGenerator generator = ColorGenerator.DEFAULT;
int color = generator.getColor(feedId); // The color is specific to the feedId (which shouldn't change)
String lettersForName = feedName != null ? (feedName.length() < 2 ? feedName.toUpperCase() : feedName.substring(0, 2).toUpperCase()) : "";
TextDrawable letterDrawable = TextDrawable.builder().buildRect(lettersForName, color);
if (mainImgUrl != null) {
Glide.with(context).load(mainImgUrl).centerCrop().placeholder(letterDrawable).error(letterDrawable).into(holder.mainImgView);
} else {
Glide.clear(holder.mainImgView);
holder.mainImgView.setImageDrawable(letterDrawable);
}
holder.isFavorite = cursor.getInt(mFavoritePos) == 1;
holder.starImgView.setVisibility(holder.isFavorite ? View.VISIBLE : View.INVISIBLE);
if (mShowFeedInfo && mFeedNamePos > -1) {
if (feedName != null) {
holder.dateTextView.setText(Html.fromHtml("<font color='#247ab0'>" + feedName + "</font>" + Constants.COMMA_SPACE + StringUtils.getDateTimeString(cursor.getLong(mDatePos))));
} else {
holder.dateTextView.setText(StringUtils.getDateTimeString(cursor.getLong(mDatePos)));
}
} else {
holder.dateTextView.setText(StringUtils.getDateTimeString(cursor.getLong(mDatePos)));
}
if (cursor.isNull(mIsReadPos)) {
holder.titleTextView.setEnabled(true);
holder.dateTextView.setEnabled(true);
holder.isRead = false;
} else {
holder.titleTextView.setEnabled(false);
holder.dateTextView.setEnabled(false);
holder.isRead = true;
}
} catch (Exception e) {}
}
}
public void toggleReadState(final long id, View view) {
final ViewHolder holder = (ViewHolder) view.getTag(R.id.holder);
if (holder != null) { // should not happen, but I had a crash with this on PlayStore...
holder.isRead = !holder.isRead;
if (holder.isRead) {
holder.titleTextView.setEnabled(false);
holder.dateTextView.setEnabled(false);
} else {
holder.titleTextView.setEnabled(true);
holder.dateTextView.setEnabled(true);
}
new Thread() {
#Override
public void run() {
ContentResolver cr = MainApplication.getContext().getContentResolver();
Uri entryUri = ContentUris.withAppendedId(mUri, id);
cr.update(entryUri, holder.isRead ? FeedData.getReadContentValues() : FeedData.getUnreadContentValues(), null, null);
}
}.start();
}
}
public void toggleFavoriteState(final long id, View view) {
final ViewHolder holder = (ViewHolder) view.getTag(R.id.holder);
if (holder != null) { // should not happen, but I had a crash with this on PlayStore...
holder.isFavorite = !holder.isFavorite;
if (holder.isFavorite) {
holder.starImgView.setVisibility(View.VISIBLE);
} else {
holder.starImgView.setVisibility(View.INVISIBLE);
}
new Thread() {
#Override
public void run() {
ContentValues values = new ContentValues();
values.put(EntryColumns.IS_FAVORITE, holder.isFavorite ? 1 : 0);
ContentResolver cr = MainApplication.getContext().getContentResolver();
Uri entryUri = ContentUris.withAppendedId(mUri, id);
cr.update(entryUri, values, null, null);
}
}.start();
}
}
#Override
public void changeCursor(Cursor cursor) {
reinit(cursor);
super.changeCursor(cursor);
}
#Override
public Cursor swapCursor(Cursor newCursor) {
reinit(newCursor);
return super.swapCursor(newCursor);
}
#Override
public void notifyDataSetChanged() {
reinit(null);
super.notifyDataSetChanged();
}
#Override
public void notifyDataSetInvalidated() {
reinit(null);
super.notifyDataSetInvalidated();
}
private void reinit(Cursor cursor) {
if (cursor != null && cursor.getCount() > 0) {
mIdPos = cursor.getColumnIndex(EntryColumns._ID);
mTitlePos = cursor.getColumnIndex(EntryColumns.TITLE);
mMainImgPos = cursor.getColumnIndex(EntryColumns.IMAGE_URL);
mDatePos = cursor.getColumnIndex(EntryColumns.DATE);
mIsReadPos = cursor.getColumnIndex(EntryColumns.IS_READ);
mFavoritePos = cursor.getColumnIndex(EntryColumns.IS_FAVORITE);
mFeedNamePos = cursor.getColumnIndex(FeedColumns.NAME);
mFeedIdPos = cursor.getColumnIndex(EntryColumns.FEED_ID);
}
}
private static class ViewHolder {
public TextView titleTextView;
public TextView dateTextView;
public ImageView mainImgView;
public ImageView starImgView;
public boolean isRead, isFavorite;
}
private static class AdsHolder {
NativeExpressAdView adView;
}
}
I have a ListView with the sections. And when there is a section, then it takes the place of another. That is, if the ListView items count 30, the section takes the place of the first paragraph, and it turns out that the show only 29 points.
Here is a picture, which shows clearly
Tried TYPE_MAX_COUNT = 2, 3. Without confusing.
#Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
I think getViewTypeCount() is triggered after getView().
private List<VacancyModel> vacancyModelList;
private LayoutInflater inflater;
private SQLHelper sqlHelper;
private static final int TYPE_SEPARATOR = 1;
private static final int TYPE_ITEM = 0;
private int rowType;
public static String saveLastDate;
private int newRecs = 0;
public SuitableAdapter(Context context, int resource, List<VacancyModel> objects) {
super(context, resource, objects);
vacancyModelList = objects;
sqlHelper = new SQLHelper(getContext());
inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#NonNull
#Override
public View getView(final int position, View convertView, #NonNull final ViewGroup parent) {
ViewHolder holder = null;
rowType = getItemViewType(position);
if (convertView == null) {
holder = new ViewHolder();
switch (rowType) {
case TYPE_SEPARATOR:
convertView = inflater.inflate(R.layout.suitable_separator_layout, null);
holder.headerTv = (TextView) convertView.findViewById(R.id.section_header);
break;
case TYPE_ITEM:
convertView = inflater.inflate(R.layout.row_layout, null);
holder.tvProfession = (TextView) convertView.findViewById(R.id.tvProfession);
holder.tvHeader = (TextView) convertView.findViewById(R.id.tvHeader);
holder.tvSalary = (TextView) convertView.findViewById(R.id.tvSalary);
holder.tvDate = (TextView) convertView.findViewById(R.id.tvPostCr);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
if (getItemViewType(position) == TYPE_SEPARATOR) {
holder.headerTv = (TextView) convertView.findViewById(R.id.section_header);
if (newRecs == 1) {
holder.headerTv.setText("Новые вакансии");
newRecs = 0;
} else {
holder.headerTv.setText("Ранее просмотренные");
}
}
if (getItemViewType(position) == TYPE_ITEM) {
final VacancyModel model = vacancyModelList.get(position);
holder.tvProfession.setText(model.getProfession());
holder.tvHeader.setText(model.getHeader());
holder.tvSalary.setText(model.getSalary());
holder.tvDate.setText(model.getDate());
Date date;
try {
if (saveLastDate == null) {
saveLastDate = model.getDate();
} else {
date = stringToDate(saveLastDate);
if (date.before(stringToDate(model.getDate()))) {
saveLastDate = model.getDate();
}
}
} catch (ParseException e) {
e.printStackTrace();
}
}
return convertView;
}
#Override
public int getItemViewType(int position) {
if (GlobalData.LoadDate(getContext()) == null) {
return TYPE_ITEM;
} else {
VacancyModel model = getItem(position);
if (model != null) {
String newString = model.getDate();
String lastString = GlobalData.LoadDate(getContext());
Date newDate = null;
Date lastDate = null;
try {
newDate = stringToDate(newString);
lastDate = stringToDate(lastString);
} catch (ParseException e) {
e.printStackTrace();
}
assert newDate != null;
if (newDate.equals(lastDate)) {
return TYPE_SEPARATOR;
} else if (position == 0 && newDate.after(lastDate)) {
newRecs = 1;
return TYPE_SEPARATOR;
} else {
return TYPE_ITEM;
}
} else {
return TYPE_ITEM;
}
}
}
#Override
public int getViewTypeCount() {
return 3;
}
#Override
public int getCount() {
return vacancyModelList.size();
}
private Date stringToDate(String string) throws ParseException {
return new SimpleDateFormat(("yyyy-MM-dd HH:mm:ss"), Locale.getDefault()).parse(string);
}
private static class ViewHolder {
private TextView tvProfession;
private TextView tvHeader;
private TextView tvSalary;
private TextView tvDate;
private TextView headerTv;
}
VacancyModel
public class VacancyModel implements Serializable{
private String profession;
private String header;
private String salary;
private String date;
public VacancyModel() {
}
public String getProfession() {
return profession;
}
public void setProfession(String profession) {
this.profession = profession;
}
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
public String getSalary() {
if (salary.equals("0") || salary.isEmpty() || salary.equals("null")){
return "empty";
}
else {
return salary;
}
}
public void setSalary(String salary) {
this.salary = salary;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
}
Question: What I am doing wrong and how to change ListView`s count?
The listItem you are sending in should have the type field as well. So what I am suggesting is instead of doing date check manipulation inside listview. you can do it prior before adding data to RecyclerView.
Adding two more Field to your Serializable Data:
public class VacancyModel implements Serializable{
private String profession;
private String header;
private String salary;
private String date;
// set setter and getter for both, by default isHeading will be false,
private boolean isHeading;
private String heading;
public VacancyModel() {
}
public String getProfession() {
return profession;
}
public void setProfession(String profession) {
this.profession = profession;
}
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
public String getSalary() {
if (salary.equals("0") || salary.isEmpty() || salary.equals("null")){
return "empty";
}
else {
return salary;
}
}
public void setSalary(String salary) {
this.salary = salary;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
}
Do the following thing inside your activity inside activity:
private void generateListHeading(List<VacancyModel> original_vacany_list)
{
List<VacancyModel> vacancy_type_new_record;
VacancyModel model = new vacacyModel();
model.setIsHeading(true);
model.setHeading("New Record");
vacancy_type_new_record.add(model);
List<VacancyModel> vacancy_type_watched;
model = new vacacyModel();
model.setIsHeading(true);
model.setHeading("Watched");
vacancy_type_watched.add(model);
List<VacancyModel> new_vacancy_list;
for(VacanyModel data:original_vacany_list)
{
//do your date condition check here
if(data.getDate==newDate)
{
vacancy_type_new_record.add(data)
} else
{
vacancy_type_watched.add(data)
}
}
//once the whole condition check is add both list to new list
new_vacancy_list.addAll(vacancy_type_new_record);
new_vacancy_list.addAll(vacancy_type_watched);
//now the item count will be 32. in the format heading ,data ,heading,data
adapter.setUpdateddata(new_vacancy_list);
}
Adapter.class:
vacanyModelList = new ArrayList<>();
public SuitableAdapter(Context context, int resource) {
super(context, resource, objects);
//don't set your object in constructor
sqlHelper = new SQLHelper(getContext());
inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#NonNull
#Override
public View getView(final int position, View convertView, #NonNull final ViewGroup parent) {
ViewHolder holder = null;
rowType = getItemViewType(position);
if (convertView == null) {
holder = new ViewHolder();
switch (rowType) {
case TYPE_SEPARATOR:
convertView = inflater.inflate(R.layout.suitable_separator_layout, null);
holder.headerTv = (TextView) convertView.findViewById(R.id.section_header);
break;
case TYPE_ITEM:
convertView = inflater.inflate(R.layout.row_layout, null);
holder.tvProfession = (TextView) convertView.findViewById(R.id.tvProfession);
holder.tvHeader = (TextView) convertView.findViewById(R.id.tvHeader);
holder.tvSalary = (TextView) convertView.findViewById(R.id.tvSalary);
holder.tvDate = (TextView) convertView.findViewById(R.id.tvPostCr);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
if (getItemViewType(position) == TYPE_SEPARATOR) {
holder.headerTv = (TextView) convertView.findViewById(R.id.section_header);
if (newRecs == 1) {
holder.headerTv.setText("Новые вакансии");
newRecs = 0;
} else {
holder.headerTv.setText("Ранее просмотренные");
}
}
if (getItemViewType(position) == TYPE_ITEM) {
final VacancyModel model = vacancyModelList.get(position);
holder.tvProfession.setText(model.getProfession());
holder.tvHeader.setText(model.getHeader());
holder.tvSalary.setText(model.getSalary());
holder.tvDate.setText(model.getDate());
Date date;
try {
if (saveLastDate == null) {
saveLastDate = model.getDate();
} else {
date = stringToDate(saveLastDate);
if (date.before(stringToDate(model.getDate()))) {
saveLastDate = model.getDate();
}
}
} catch (ParseException e) {
e.printStackTrace();
}
}
return convertView;
}
#Override
public int getItemViewType(int position) {
VacancyModel model = getItem(position);
if (model.isHeading) {
return TYPE_SEPARATOR;
} else {
return TYPE_ITEM;
}
}
}
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getCount() {
return vacancyModelList.size();
}
private Date stringToDate(String string) throws ParseException {
return new SimpleDateFormat(("yyyy-MM-dd HH:mm:ss"), Locale.getDefault()).parse(string);
}
private static class ViewHolder {
private TextView tvProfession;
private TextView tvHeader;
private TextView tvSalary;
private TextView tvDate;
private TextView headerTv;
}
public void setUpdatedData(List<VacancyModel> updated_list)
{
this.vacancyModelList = updated_list;
notifyDataSetChanged();
}
I'm using Parse in my app, and in order to load my 'profile' images, I need to retrieve a so called Parsefile. When the Parsefile is downloaded it uses a callback to notify when it's done. Now this is generally a nice way to do things but I encountered a problem with this when using a Listview and downloading the images with an Asynctask.
The problem is as follows:
In my ListView adapter in the getView method, I create an AsyncTask and execute it, this AsyncTask starts the retrieveProfileImage(callBack) function. In my callback I simply start a Runnable on the UI thread to update the ImageView in the View with the new (retrieved Image). The problem however as it seems, is the fact that as soon as I start my AsyncTask, the View is returned. So I can't set the other images to the correct row. I hope my code demonstrates my problem more clearly.
The ListAdapter:
public class FriendListAdapter extends ArrayAdapter<Profile> {
private int resource;
private Context context;
private List<Profile> friends;
private Profile fProfile;
private Bitmap profileImageBitmap;
private ProgressBar friendImageProgressBar;
//ui
private ImageView friendImage;
public FriendListAdapter(Context context, int resource,
List<Profile> objects) {
super(context, resource, objects);
this.context = context;
this.resource = resource;
this.friends = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView friendName = null;
friendImage = null;
View rowView = convertView;
if (rowView == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
rowView = inflater.inflate(R.layout.friendslist_row, null);
friendName = (TextView) rowView.findViewById(R.id.fName);
friendImage = (ImageView) rowView
.findViewById(R.id.fImage);
friendImageProgressBar = (ProgressBar) rowView.findViewById(R.id.friendImageProgressBar);
} else {
friendName = (TextView) convertView.findViewById(R.id.fName);
friendImage = (ImageView) convertView.findViewById(R.id.fImage);
friendImageProgressBar = (ProgressBar) convertView.findViewById(R.id.friendImageProgressBar);
}
fProfile = friends.get(position);
DownloadProfileImage dImg = new DownloadProfileImage();
dImg.execute();
friendName.setText(fProfile.getName());
return rowView;
}
private class DownloadProfileImage extends AsyncTask<Void, Integer, String> {
#Override
protected String doInBackground(Void... arg0) {
Log.d("logpp", "Starting download image for " + fProfile.getName());
fProfile.retrieveProfileImage(new ProfileImageCallback());
return null;
}
}
private class ProfileImageCallback extends GetDataCallback {
#Override
public void done(byte[] bytearray, ParseException e) {
if (e == null) {
Log.d("logpp", "Done downloading image for " + fProfile.getName() + ". Setting bitmap to:" +
" " + friendImage.getId());
profileImageBitmap = BitmapManager
.getBitmapFromByteArray(bytearray);
((Activity) context).runOnUiThread(new UpdateUi());
}
}
}
private class UpdateUi implements Runnable {
#Override
public void run() {
friendImage.setImageBitmap(profileImageBitmap);
friendImage.setVisibility(View.VISIBLE);
friendImageProgressBar.setVisibility(View.INVISIBLE);
}
}
}
The retrieveProfileImage method:
public void retrieveProfileImage(GetDataCallback callBack) {
this.image.getDataInBackground(callBack);
}
I hope someone can help me with this one.
Regards,
Tim
i solved this problem by following code
public View getView(int position, View convertView, ViewGroup parent) {
try {
if (inflater == null)
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.answer_item, null);
TextView name = (TextView) convertView.findViewById(R.id.textView_ans_user_name);
TextView body = (TextView) convertView.findViewById(R.id.textView_ans_user_body);
TextView timestamp = (TextView) convertView.findViewById(R.id.textView_ans_user_timestamp);
final CircularImageView thumbnail = (CircularImageView) convertView.findViewById(R.id.imageView_ans_user);
Parse_answer_model ans = answers.get(position);
name.setText(ans.getAns_by());
body.setText(ans.getAns_body());
SimpleDateFormat sdfAmerica = new SimpleDateFormat("dd-M-yyyy hh:mm:ss a");
sdfAmerica.setTimeZone(TimeZone.getDefault());
String sDateInAmerica = sdfAmerica.format(ans.getCreatedAt());
timestamp.setText(sDateInAmerica);
ParseQuery<User> query = ParseQuery.getQuery("_User");
query.whereEqualTo("username", ans.getAns_by());
query.getFirstInBackground(new GetCallback<User>() {
public void done(User user, ParseException e) {
// TODO Auto-generated method stub
if (e == null) {
img.DisplayImage(user.getprofile_pic_url(), thumbnail, false);
} else {
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
put your imageview as final dont make it global and you get image url from geturl() method, it is as defined by parse you can use below example
ParseFile fileObject = (ParseFile) object.get("image_file");
User user = new User();
user = (User) ParseUser.getCurrentUser();
user.setProfile_pic_url(fileObject.getUrl().toString());
user.saveInBackground();
update
last day i found new solution you can get user's data which related to parse object by following code and made some changes in model class,too.
void getchats() {
pd.show();
ParseQuery<Parse_chat_dialogs> query = ParseQuery.getQuery("chat_dialogs");
query.addDescendingOrder("updatedAt");
query.whereContains("users", ParseUser.getCurrentUser().getUsername());
query.findInBackground(new FindCallback<Parse_chat_dialogs>() {
public void done(List<Parse_chat_dialogs> dilogs, ParseException e) {
if (e == null) {
pd.hide();
dialoglist = (ArrayList<Parse_chat_dialogs>) dilogs;
adp = new ChatDialogAdapter(Chat_list.this, dialoglist);
list.setAdapter(adp);
for (int i = 0; i < dialoglist.size(); i++) {
ParseQuery<User> query = ParseQuery.getQuery("_User");
query.whereEqualTo("username", dialoglist.get(i).getUsers().trim()
.replace(ParseUser.getCurrentUser().getUsername(), "").replace(",", ""));
User user = new User();
try {
user = query.getFirst();
dialoglist.get(i).setFirstname(user.getFirstname());
dialoglist.get(i).setLastname(user.getLastname());
dialoglist.get(i).setProfileurl(user.getprofile_pic_url());
adp.notifyDataSetChanged();
} catch (ParseException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
} else {
Toast.makeText(Chat_list.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
}
as in above example i added three new param in parseobejct model class for storing values of user's firstname ,lastname and profile url.
i am also sharing model class for getting more idea
#ParseClassName("chat_dialogs")
public class Parse_chat_dialogs extends ParseObject {
private String firstname;
private String lastname;
private String profileurl;
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getProfileurl() {
return profileurl;
}
public void setProfileurl(String profileurl) {
this.profileurl = profileurl;
}
/////////////////////////////////////////////////////////////////////////////
public String getLast_message() {
return getString("last_message");
}
public void setLast_message(String value) {
put("last_message", value);
}
public String getUsers() {
return getString("users");
}
public void setUsers(String value) {
put("users", value);
}
}
How about this!
Instead of using AsyncTask in the adapter class, use it in the MainActivity where you set the adapter for the listview. And in your done method in the Callback or the postExecute update the object/objects and call notifyDataSetChanged().
So, essentially you could have an update method in your adapter class, say, like this,
public void updateObject(int pos, byte[] byteArray){
//Assuming your Profile Object has some member to store this image data
friends.get(pos).setImageData(byteArray); //friends is the list in adapter class and setImageData may be the setter in your Profile object class
notifyDataSetChanged();
}
and in the getView(), you could do something like this
profileImageBitmap = BitmapManager
.getBitmapFromByteArray(friends.get(pos).getImageData);
friendImage.setImageBitmap(profileImageBitmap);