I am trying to make an app similar to Action Launcher, but I am hitting some bumps in the road. I can't seem to get the installed apps to populate in a fragment.
It either crashes or it just doesn't populate with the apps (the view of the apps). I currently have it set up to load all apps into an ArrayList/List, that has 90 apps installed so that I'm not worried about. It's displaying the actual apps that I am having the hardest time with. I am trying to do this dynamically, and it's not working the way I want it to.
/*
* Assume that
* GridView gv;
* Config cnf = new Config(); //personal class
* PackageManager pm;
* pm = getPackageManager();
*
*/
public void SelectItem(int possition) {
switch(possition){
case 2:
gv = (GridView) findViewById(R.id.gridView1);
// ArrayList<Apps> apps = cnf.getApps();
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> apps = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
GridLayout gl = new GridLayout(returnContext());
gl.setOrientation(GridLayout.VERTICAL);
for (ResolveInfo appInfo : apps) {
String label = (String) appInfo.loadLabel(pm);
TextView name2 = new TextView(returnContext());
name2.setText(label);
gl.addView(name2);
ImageView img = new ImageView(returnContext());
img.setImageDrawable(appInfo.loadIcon(pm));
gl.addView(img);
}
gv.addView(gl); // I am getting a null reference exception here
}
}
And the Base XML for the above code
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<GridView
android:id="#+id/gridView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:columnWidth="40dp"
android:gravity="center"
android:numColumns="auto_fit"
android:stretchMode="columnWidth" >
<ImageView
android:id="#+id/appicon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:layout_marginBottom="2dip"
android:layout_marginLeft="2dip"
android:layout_marginRight="6dip"
android:layout_marginTop="2dip"
android:scaleType="fitCenter" />
<TextView
android:id="#+id/apptitle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textSize="20dip" />
</GridView>
</RelativeLayout>
I am assuming that my issue lies with the obvious (I am not setting a value properly.) and not the bigger issue of I don't know what I am doing and I messed something up (which I don't and probably did)
I uploaded my source to GitHub :)
Cheers.
Since absolutely no one came even with a simple suggestion, I figured it out myself like a good little programmer.
This solution will list out all of the installed apps, with the inclusion of all apps with the Intent.CATEGORY_LAUNCHER, without including all of the system apps. I will admit it is slow to populate but the end solution is to actually use a database to help aid in loading all of the items.
Since I have released this solution on github I have these licensed under the MIT licence.
So the following is the solution.
public List<Apps> listAllApps() {
List<Apps> apps = new ArrayList<Apps>();
List<ApplicationInfo> appinfo = pm.getInstalledApplications(0);
Apps app;
i = 0;
List<String> appnames = appNames();
for (int j = 0; j < appinfo.size(); j++) {
if (Config.in_array(appnames, appinfo.get(j).packageName)) {
app = new Apps();
app.setPackageName(appinfo.get(j).packageName);
app.setTitle(appinfo.get(j).loadLabel(pm).toString());
apps.add(app);
if (appinfo.get(j).packageName.contains("gallery") ||
appinfo.get(j).loadLabel(pm).toString().contains("gallery")) {
if (appinfo.get(j).name.contains("gallery")) {
setGalleryPackage(i, appinfo.get(j).packageName);
} else
setGalleryPackage(i, appinfo.get(j).packageName);
i++;
}
}
}
return apps;
}
public List appNames() {
final Intent mainIntent = new Intent(Intent.ACTION_MAIN);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> packs = pm.queryIntentActivities(mainIntent, 0);
List<String> appNames = new ArrayList<String>(packs.size());
for (ResolveInfo ai : packs) {
appNames.add(ai.activityInfo.packageName.toString());
}
return appNames;
}
To actually add the items to the screen I had to put the following inside the (fragment) onCreateView method
List<Apps> loadedApps = listAllApps();
Collections.sort(loadedApps, new Comparator<Apps>() {
#Override
public int compare(Apps lhs, Apps rhs) {
return lhs.getTitle().compareTo(rhs.getTitle());
}
});
// Config.makeColdToast(loadedApps.size());
for (final Apps a : loadedApps) {
final TableRow tb = new TableRow(Config.context);
tb.setId(i + 1000);
Drawable ico = null;
try {
Intent in = pm.getLaunchIntentForPackage(a.getPackageName());
if (in != null) {
ico = pm.getActivityIcon(in);
}
} catch (NameNotFoundException e) {
}
ImageView ima = new ImageView(Config.context);
ima.setImageDrawable(ico);
tb.addView(ima, new TableRow.LayoutParams(Config.dpToPx(50), Config.dpToPx(50)));
TextView name = new TextView(Config.context);
name.setText(a.getTitle());
a.setID(i);
tb.setPadding(Config.dpToPx(25), Config.dpToPx(10), Config.dpToPx(15), Config.dpToPx(10));
tb.setBackgroundColor(Color.argb(125, 0, 0, 0));
tb.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = Config.context.getPackageManager().getLaunchIntentForPackage(a.getPackageName());
if (intent != null) {
startActivity(intent);
}
tb.setBackgroundColor(Color.TRANSPARENT);
}
});
tb.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View arg0) {
Config.makeColdToast("Long click!");
return false;
}
});
tb.addView(name, new TableRow.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
gv.addView(tb, new TableLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
/*
* This is the gray line...
*/
TableRow tl = new TableRow(Config.context);
tl.setBackgroundResource(R.layout.customborder);
gv.addView(tl);
i++;
}
And finally the Apps class that is referenced several times.
public class Apps {
private String title;
private String packageName;
private String versionName;
private int versionCode;
private String description;
private ResolveInfo resolveinfo;
Intent intent;
private int id;
public String getTitle() {
return title;
}
public void setResolveInfo(ResolveInfo ri) {
this.resolveinfo = ri;
}
public ResolveInfo getResolveInfo() {
return this.resolveinfo;
}
public int getID() {
return id;
}
public void setID(int id) {
this.id = id;
}
public void setTitle(String title) {
this.title = title;
}
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public String getVersionName() {
return versionName;
}
public void setVersionName(String versionName) {
this.versionName = versionName;
}
public int getVersionCode() {
return versionCode;
}
public void setVersionCode(int versionCode) {
this.versionCode = versionCode;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public class AppViewHolder {
public TextView mTitle;
public ImageView mIcon;
public void setTitle(String title) {
mTitle.setText(title);
}
public void setIcon(Drawable img) {
if (img != null) {
mIcon.setImageDrawable(img);
}
}
}
public Drawable mIcon;
public void setIcons(Drawable icon) {
mIcon = icon;
}
public Drawable getIcon() {
return mIcon;
}
}
Related
I have an app that utilizes a TSL 1128 reader to read RFID tags. It uses the IASCIICommandResponder Library to communicate with the reader.
I have one Class called orderFullfill.java that is responsible for the Listview and updating the UI for this class. Th
The Reader functionality is set up in another class (orderResponder.java) that implements this IASCIICommandResponder, so that it can run in the background whilst orderFullfill shows the changes made to the ArrayList.
I have tried passing the Arrayadapter from orderFullfill.java to orderResponder to call notifyDataSetChanged(); but that has no effect. I have to call addPigNumber() method on a button click to update my listview.
Ideally I need the listview to update when a new tag is added to the list. Please can someone help me apply notifyDataSetChanged() in the right place so that when I can a tag it will add to the list automatically. I am very grateful for any help that is received.
public class orderFullfill extends AppCompatActivity implements PopupMenu.OnMenuItemClickListener {int where; public static ArrayList scannedPigs = new ArrayList<String>();
// The Reader currently in use
private Reader mReader = null;
private boolean mIsSelectingReader = false;
// The model that performs actions with the reader
private TriggerModel mModel;
public static String dispatchweek;
public static String customer;
public static String accountnumber;
public static String supplyfarm;
public static String breed;
public static int numberofpigs;
public static int pigNum;
public static ArrayAdapter<String> adapter;
public static String weekNow;
public static Context mContext;
Switch trick; TextView nameholder;
/**
* #return the current AsciiCommander
*/
protected AsciiCommander getCommander()
{
return AsciiCommander.sharedInstance();
}
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.orderfullfill);
mContext = orderFullfill.this;
addPigNumber();
InventoryCommand iCommand = InventoryCommand.synchronousCommand();
iCommand.setFilterStrongest(TriState.YES);//high power reading
trick = (Switch) findViewById(R.id.scanM2);
trick.setVisibility(View.INVISIBLE);
trick.setChecked(true);
trick.setText(getResources().getString(R.string.lowPowerScan));
trick.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
InventoryCommand iCommand = new InventoryCommand();
//InventoryCommand iCommand = InventoryCommand.synchronousCommand();
if(isChecked)
{
iCommand.setTakeNoAction(TriState.YES);
iCommand.setFilterStrongest(TriState.YES);// low power reading
getCommander().executeCommand(iCommand);
trick.setText(getResources().getString(R.string.lowPowerScan));
}
if(!isChecked)
{
trick.setText(getResources().getString(R.string.highPowerScan));
iCommand.setFilterStrongest(TriState.NO);//high power reading
iCommand.setTakeNoAction(TriState.NO);
getCommander().executeCommand(iCommand);
}
}
});
nameholder = (TextView)findViewById(R.id.nameView);
nameholder.setText(customer);
AsciiCommander.createSharedInstance(getApplicationContext());
final AsciiCommander commander = getCommander();
// Ensure that all existing responders are removed
commander.clearResponders();
// Add the LoggerResponder - this simply echoes all lines received from the reader to the log
// and passes the line onto the next responder
// This is ADDED FIRST so that no other responder can consume received lines before they are logged.
// commander.addResponder(new LoggerResponder());// logcat input
// Add responder to enable the synchronous commands
// commander.addSynchronousResponder();
commander.addResponder(new orderResponder());
// Configure the ReaderManager when necessary
ReaderManager.create(getApplicationContext());
// Add observers for changes
ReaderManager.sharedInstance().getReaderList().readerAddedEvent().addObserver(mAddedObserver);
ReaderManager.sharedInstance().getReaderList().readerUpdatedEvent().addObserver(mUpdatedObserver);
ReaderManager.sharedInstance().getReaderList().readerRemovedEvent().addObserver(mRemovedObserver);
// Create a (custom) model and configure its commander and handler
mModel = new TriggerModel();
mModel.setCommander(getCommander());
mModel.initialise();
ListView scroller = (ListView)findViewById(R.id.listviewD);
scroller.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
PopupMenu popup = new PopupMenu(orderFullfill.this, view);
popup.setOnMenuItemClickListener(orderFullfill.this);
popup.inflate(R.menu.edit_menu);
where = position;
popup.show();
}
});
weekNow = orderResponder.getWeeknow();
}
public ArrayAdapter getAdapter()
{
adapter = new ArrayAdapter<>(mContext, android.R.layout.simple_spinner_item, scannedPigs);
return adapter;
}
public void addPigNumber()
{
adapter = new ArrayAdapter<String>(mContext, android.R.layout.simple_spinner_item, scannedPigs);
TextView counter = findViewById(R.id.editTextNumber);
if(numberofpigs >= 0 )
{
counter.setText("Pigs Left: " +numberofpigs);
if(numberofpigs == 0)
{
counter.setBackgroundColor(Color.parseColor("#BCBDF3E8"));
}
}
ListView scroller = findViewById(R.id.listviewD);
try {
adapter.setDropDownViewResource(R.layout.support_simple_spinner_dropdown_item);
scroller.setAdapter(adapter);
}catch (Exception e)
{
String result ="";
result.equals(e.toString());
}
}
public void orderdetailsOnclick(View view) {
addPigNumber();
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Customer Order: " + customer);
alert.setMessage("Account Number: " + accountnumber + "\r\n" +
"Dispatch Week: " + dispatchweek + "\r\n" +
"Supply Farm: " + supplyfarm + "\r\n" +
"Breed: "+ breed + "\r\n" + "Number of Pigs: " + pigNum);
alert.setCancelable(true);
alert.show();
}
#Override
public synchronized void onResume()
{
super.onResume();
addPigNumber();
// Register to receive notifications from the AsciiCommander
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter(AsciiCommander.STATE_CHANGED_NOTIFICATION));
// Remember if the pause/resume was caused by ReaderManager - this will be cleared when ReaderManager.onResume() is called
boolean readerManagerDidCauseOnPause = ReaderManager.sharedInstance().didCauseOnPause();
// The ReaderManager needs to know about Activity lifecycle changes
ReaderManager.sharedInstance().onResume();
// The Activity may start with a reader already connected (perhaps by another App)
// Update the ReaderList which will add any unknown reader, firing events appropriately
ReaderManager.sharedInstance().updateList();
// Locate a Reader to use when necessary
AutoSelectReader(!readerManagerDidCauseOnPause);
mIsSelectingReader = false;
displayReaderState();
}
#Override
public synchronized void onPause() {
super.onPause();
// Register to receive notifications from the AsciiCommander
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
addPigNumber();
ReaderManager.sharedInstance().onPause();
}
#Override
protected void onDestroy()
{
super.onDestroy();
// Remove observers for changes
ReaderManager.sharedInstance().getReaderList().readerAddedEvent().removeObserver(mAddedObserver);
ReaderManager.sharedInstance().getReaderList().readerUpdatedEvent().removeObserver(mUpdatedObserver);
ReaderManager.sharedInstance().getReaderList().readerRemovedEvent().removeObserver(mRemovedObserver);
// readResponder.tempList = false;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.reader_menu, menu);
// Reset, connect, disconnect dropdown menu
mResetMenuItem = menu.findItem(R.id.reset_reader_menu_item);
mConnectMenuItem = menu.findItem(R.id.connect_reader_menu_item);
mDisconnectMenuItem= menu.findItem(R.id.disconnect_reader_menu_item);
return true;
}
//----------------------------------------------------------------------------------------------
// ReaderList Observers
//----------------------------------------------------------------------------------------------
Observable.Observer<Reader> mAddedObserver = new Observable.Observer<Reader>()
{
#Override
public void update(Observable<? extends Reader> observable, Reader reader)
{
// See if this newly added Reader should be used
AutoSelectReader(true);
}
};
Observable.Observer<Reader> mUpdatedObserver = new Observable.Observer<Reader>()
{
#Override
public void update(Observable<? extends Reader> observable, Reader reader)
{
}
};
Observable.Observer<Reader> mRemovedObserver = new Observable.Observer<Reader>()
{
#Override
public void update(Observable<? extends Reader> observable, Reader reader)
{
// Was the current Reader removed
if( reader == mReader)
{
mReader = null;
// Stop using the old Reader
getCommander().setReader(mReader);
}
}
};
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId())
{
case R.id.delete_menu:
boolean complete = false;
scannedPigs.remove(where);
numberofpigs = numberofpigs + 1;
//myDB.deleteEntry(scannedItems); -> IF YOU ADD IT TO THE DB REMOVE IT
//select items from the list
addPigNumber();
return true;
case R.id.edit_menu_:
return true;
}
return super.onOptionsItemSelected(item);
}}
orderfullfill.xml
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.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"
android:orientation="vertical">
<TextView
android:id="#+id/editTextNumber"
android:layout_width="177dp"
android:layout_height="56dp"
android:layout_marginStart="24dp"
android:layout_marginLeft="24dp"
android:layout_marginTop="80dp"
android:textSize="30sp"
app:layout_constraintBottom_toTopOf="#+id/listviewD"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />
<ListView
android:id="#+id/listviewD"
android:layout_width="354dp"
android:layout_height="221dp"
android:layout_marginBottom="12dp"
app:layout_constraintBottom_toTopOf="#+id/scanM2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.421"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="#+id/invoiceMaker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="#string/makeInvoice"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.75"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/scanM2" />
<TextView
android:id="#+id/nameView"
android:layout_width="333dp"
android:layout_height="52dp"
android:layout_marginLeft="25dp"
android:layout_marginTop="16dp"
android:layout_marginRight="25dp"
android:layout_marginBottom="303dp"
android:textSize="20dp"
app:layout_constraintBottom_toTopOf="#+id/scanM2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<Button
android:id="#+id/orderdetailsBtn"
android:layout_width="119dp"
android:layout_height="54dp"
android:layout_marginTop="68dp"
android:layout_marginEnd="20dp"
android:layout_marginRight="20dp"
android:onClick="orderdetailsOnclick"
android:text="#string/showOrder"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.887"
app:layout_constraintStart_toEndOf="#+id/editTextNumber"
app:layout_constraintTop_toTopOf="parent" />
<Switch
android:id="#+id/scanM2"
android:layout_width="359dp"
android:layout_height="39dp"
android:layout_below="#id/listviewD"
android:layout_marginTop="232dp"
android:text="#string/highPowerScan"
android:textOff="No"
android:textOn="Yes"
android:textSize="27dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.461"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/orderdetailsBtn" />/android.support.constraint.ConstraintLayout>
orderResponder.java -> this is the class that the TSL reader communicates with via ASCII when reading RFID tags. The method Splicer adds the RFID values to the ArrayAdapter then notifyDataSetChanged(); is called. However nothing happens when this method is called from outside orderFullfill.class.
public class orderResponder extends Application implements IAsciiCommandResponder {
public static boolean tempList;
NoteHelper myDB;
public List<String> getReadInput() {
return readInput;
}
public void setReadInput(List<String> readInput) {
this.readInput = readInput;
}
public static List<String> readInput = new ArrayList<>();
#Override
public boolean isResponseFinished() {
return false;
}
#Override
public void clearLastResponse() {
}
#Override
public boolean processReceivedLine(String s, boolean b) throws Exception {
isitMe(s);
return false;
}
public List<String> getList()
{
return readInput;
}
public boolean isitMe (String input)
{
String firstFourChars = "";
//get first 4 chars to see if it contains "EP: "
if(input.length()>4)
{
firstFourChars = input.substring(0,4);
}
else
{
firstFourChars = input;
}
if(firstFourChars.equals("EP: "))// this is the inital identifier for the RFID tags
{
splicer(input);
return true;
}
else
{
return false;
}
}
//takes the last 24 characters removing the 'EP: '
public void splicer (String input)
{ // ArrayAdapter magic = orderFullfill.getAdapter(); THIS Didnt work
orderFullfill.adapter = new ArrayAdapter<String>(orderFullfill.mContext, android.R.layout.simple_spinner_item, orderFullfill.scannedPigs);
String output ="";
output = input.substring(input.length() -24);//maybe take 24 chars
if (orderFullfill.scannedPigs.size() == 0) {
// orderFullfill.scannedPigs.add(output);
orderFullfill.adapter.add(output);
orderFullfill.adapter.notifyDataSetChanged();
orderFullfill.numberofpigs = orderFullfill.numberofpigs - 1;
} else//if the list has values check you are not duplicating the values
{
if (orderFullfill.scannedPigs.contains(output)) {
return;//you are already in the list
} else//you are unique you can join the list
{
// orderFullfill.scannedPigs.add(output);
orderFullfill.adapter.add(output);
orderFullfill.adapter.notifyDataSetChanged();
orderFullfill.numberofpigs = orderFullfill.numberofpigs - 1;
}
}
}
public static String getWeeknow()
{
Date date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
String dateH = formatter.format(date);
//String dateH = date.toString();
String[] array = dateH.split("\\/");
String output ="";
int month = Integer.parseInt(array[1]);
month = month -1;
Calendar calendar = Calendar.getInstance();
calendar.set(Integer.parseInt(array[2]),month,Integer.parseInt(array[0]));
int weekOfyear = calendar.get(Calendar.WEEK_OF_YEAR);
output = String.valueOf(weekOfyear);
return output;
}}
create orderResponder constructor method. and send your activity(orderFullfill.this) and context to orderResponder as parameter. call like this;
((orderFullfill)activity).adapter = new ArrayAdapter<String>(context, android.R.layout.simple_spinner_item, ((orderFullfill)activity).scannedPigs);
((orderFullfill)activity).adapter.notifyDataSetChanged();
i hope it works.
I have data on firebase, the data is shown in recyclerview. I have so many recyclerviews showing. Above a recyclerview I have a textview where I want to show the total number of recyclerviews. I have also a button so that when I click on it does the count and show the result in a textview. In summary: If i click a button i want to see the number of recyclerviews in a textview.
Here is my .xml code:
<RelativeLayout
android:id="#+id/rlRunning"
android:background="#00ff0000"
android:layout_below="#+id/rl"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/del_t"
android:text="mmmm"
android:textSize="30sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:onClick="clickMe"
android:id="#+id/btn_t"
android:layout_below="#+id/del_t"
android:text="Click me"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<android.support.v7.widget.RecyclerView
android:layout_below="#+id/btn_t"
android:id="#+id/recyclerview"
android:background="#00ff0000"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
Here is my adapter:
public class BlogzoneImages {
private String ititle, idate, idesc,imageUrl;
public BlogzoneImages(String ititle, String idate, String imageUrl, String idesc ) {
this.idate = idate;
this.ititle = ititle;
this.idesc = idesc;
this.imageUrl=imageUrl;
}
public BlogzoneImages() {
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public void setiDate(String idate) {
this.idate = idate;
}
public void setiTitle(String ititle) {
this.ititle = ititle;
}
public void setiDesc(String idesc) {
this.idesc = idesc;
}
public String getImageUrl() {
return imageUrl;
}
public String getiDate() {
return idate;
}
public String getiTitle() {
return ititle;
}
public String getiDesc() {
return idesc;
}
}
Here is how I am getting the data to display in MainActivity.java
protected void loadImage_setups() {
mAuth.addAuthStateListener(mAuthListener);
FirebaseRecyclerAdapter<BlogzoneImages, BlogzoneViewHolder2> FBRA_Images = new FirebaseRecyclerAdapter<BlogzoneImages, BlogzoneViewHolder2>(
BlogzoneImages.class,
R.layout.setups_card,
BlogzoneViewHolder2.class,
image_Database
) {
#Override
protected void populateViewHolder(BlogzoneViewHolder2 viewHolder, BlogzoneImages model, int position) {
final String post_key = getRef(position).getKey().toString();
viewHolder.setiDate(model.getiDate());
viewHolder.setiTitle(model.getiTitle());
viewHolder.setiDesc(model.getiDesc());
viewHolder.setImageUrl(getApplicationContext(), model.getImageUrl());
viewHolder.mView2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Intent singleActivity = new Intent(MainActivity.this, SinglePostActivity.class);
// singleActivity.putExtra("PostID", post_key);
// startActivity(singleActivity);
}
});
}
};
recyclerView.setAdapter(FBRA_Images);
}
public static class BlogzoneViewHolder2 extends RecyclerView.ViewHolder {
View mView2;
public BlogzoneViewHolder2(View itemView2) {
super(itemView2);
mView2 = itemView2;
}
public void setiDate(String idate) {
TextView post_date = mView2.findViewById(R.id.setup_date);
post_date.setText(idate);
}
public void setiTitle(String ititle) {
TextView post_title = mView2.findViewById(R.id.setup_title);
post_title.setText(ititle);
}
public void setiDesc(String idesc) {
TextView post_desc = mView2.findViewById(R.id.setup_desc);
post_desc.setText(idesc);
}
public void setImageUrl(Context ctx, String imageUrl) {
ImageView post_image = mView2.findViewById(R.id.setup_image);
Picasso.with(ctx).load(imageUrl).into(post_image);
}
}
All this is well, the data is showing nicely on recyclerview.
My worry now is to show the total number of these recyclerviews in a texview when i click the button.
I have tried this in MainActivity.java:
int count = 0;
public void showTotal() {
RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recyclerview);
if (recyclerView.getAdapter() != null) {
count = recyclerView.getAdapter().getItemCount();
}
TextView tvvv = (TextView)findViewById(R.id.del_t);
tvvv.setText(count);
}
public void clickMe(View view) {
showTotal();
}
When i click the button, the app crashes. I have also tried this:
public void showTotal() {
RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recyclerview);
int itemCount = recyclerView.getAdapter().getItemCount();
TextView tvvv = (TextView)findViewById(R.id.del_t);
tvvv.setText(itemCount);
}
public void clickMe(View view) {
showTotal();
}
When I click the button, the app crashes again. So now I am stuck. I have no idea how to solve this. My question is, how can i show the total number of recyclerviews in a TextView after a button click?
I try to implement MVVM by Mindorks to show data from here :(https://api.themoviedb.org/3/movie/384018?api_key=67bc513a7a353631119fdffe5f7377a8&language=en-US) in my Activity. I try using databinding for update UI, everything is going well untill I try to rotate my screen, I see from my logcat the data is always reload and my ImageView is always refresh, this is my Activity:
public class DetailActivity extends BaseActivity<ActivityDetailBinding, DetailViewModel> implements DetailNavigator {
#Inject
ViewModelProviderFactory factory;
private DetailViewModel detailViewModel;
public static final String INTENT_ID = "id_intent";
public static final String INTENT_FLAG = "id_flag";
private ActivityDetailBinding mActivityDetailBinding;
public static Intent newIntent(Context context) {
return new Intent(context, DetailActivity.class);
}
#Override
public int getBindingVariable() {
return BR.viewModel;
}
#Override
public int getLayoutId() {
return R.layout.activity_detail;
}
#Override
public DetailViewModel getViewModel() {
detailViewModel = ViewModelProviders.of(this, factory).get(DetailViewModel.class);
return detailViewModel;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
detailViewModel.setNavigator(this);
mActivityDetailBinding = getViewDataBinding();
initView();
initData(savedInstanceState);
}
private void initData(Bundle savedInstanceState) {
Bundle extras = getIntent().getExtras();
if (extras != null) {
int id = extras.getInt(INTENT_ID, 0);
int flag = extras.getInt(INTENT_FLAG, 0);
detailViewModel.fetchDetail(id, flag);
}
}
private void initView() {
if (getSupportActionBar() != null) {
getSupportActionBar().hide();
}
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
#Override
public void ShowProgressDialog(Boolean loading) {
if (loading) {
showLoading();
} else {
hideLoading();
}
}
}
and my BaseActivity like this :
public abstract class BaseActivity<T extends ViewDataBinding, V extends BaseViewModel> extends AppCompatActivity
implements BaseFragment.Callback {
// TODO
// this can probably depend on isLoading variable of BaseViewModel,
// since its going to be common for all the activities
private ProgressDialog mProgressDialog;
private T mViewDataBinding;
private V mViewModel;
/**
* Override for set binding variable
*
* #return variable id
*/
public abstract int getBindingVariable();
/**
* #return layout resource id
*/
public abstract
#LayoutRes
int getLayoutId();
/**
* Override for set view model
*
* #return view model instance
*/
public abstract V getViewModel();
#Override
public void onFragmentAttached() {
}
#Override
public void onFragmentDetached(String tag) {
}
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
performDependencyInjection();
super.onCreate(savedInstanceState);
performDataBinding();
}
public T getViewDataBinding() {
return mViewDataBinding;
}
#TargetApi(Build.VERSION_CODES.M)
public boolean hasPermission(String permission) {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
}
public void hideKeyboard() {
View view = this.getCurrentFocus();
if (view != null) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
}
public void hideLoading() {
if (mProgressDialog != null && mProgressDialog.isShowing()) {
mProgressDialog.cancel();
}
}
public void showLoading() {
hideLoading();
mProgressDialog = CommonUtils.showLoadingDialog(this);
}
public boolean isNetworkConnected() {
return NetworkUtils.isNetworkConnected(getApplicationContext());
}
public void performDependencyInjection() {
AndroidInjection.inject(this);
}
#TargetApi(Build.VERSION_CODES.M)
public void requestPermissionsSafely(String[] permissions, int requestCode) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(permissions, requestCode);
}
}
// public void showLoading() {
// hideLoading();
// mProgressDialog = CommonUtils.showLoadingDialog(this);
// }
private void performDataBinding() {
mViewDataBinding = DataBindingUtil.setContentView(this, getLayoutId());
this.mViewModel = mViewModel == null ? getViewModel() : mViewModel;
mViewDataBinding.setVariable(getBindingVariable(), mViewModel);
mViewDataBinding.setLifecycleOwner(this);
mViewDataBinding.executePendingBindings();
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onDestroy() {
super.onDestroy();
}
}
this is my ViewModelFactory class :
#Singleton
public class ViewModelProviderFactory extends ViewModelProvider.NewInstanceFactory {
private final DataManager dataManager;
private final SchedulerProvider schedulerProvider;
#Inject
public ViewModelProviderFactory(DataManager dataManager,
SchedulerProvider schedulerProvider) {
this.dataManager = dataManager;
this.schedulerProvider = schedulerProvider;
}
#Override
public <T extends ViewModel> T create(Class<T> modelClass) {
if (modelClass.isAssignableFrom(DetailViewModel.class)) {
return (T) new DetailViewModel(dataManager,schedulerProvider);
}
throw new IllegalArgumentException("Unknown class name");
}
}
this is my ViewModel class :
public class DetailViewModel extends BaseViewModel<DetailNavigator> {
private final ObservableField<String> originalName = new ObservableField<>();
private final ObservableField<String> releaseDate = new ObservableField<>();
private final ObservableField<String> overview = new ObservableField<>();
private final ObservableField<String> genreMovie = new ObservableField<>();
private final ObservableField<String> posterPath = new ObservableField<>();
private final ObservableField<String> voteAverage = new ObservableField<>();
public DetailViewModel(DataManager dataManager, SchedulerProvider schedulerProvider) {
super(dataManager, schedulerProvider);
}
public void fetchDetail(int id, int flag) {
if (flag == 1) {
getNavigator().ShowProgressDialog(true);
getCompositeDisposable().add(getDataManager()
.getApiHelper().doDetailMovie(id, URLConfig.API_KEY, getDataManager().getLanguage())
.subscribeOn(getSchedulerProvider().io())
.observeOn(getSchedulerProvider().ui())
.subscribe(detailResponse -> {
setUpData(detailResponse);
getNavigator().ShowProgressDialog(false);
// getNavigator().updateView();
}, throwable -> {
getNavigator().ShowProgressDialog(false);
}));
} else if (flag == 2) {
getNavigator().ShowProgressDialog(true);
getCompositeDisposable().add(getDataManager()
.getApiHelper().doDetailTV(id, URLConfig.API_KEY, getDataManager().getLanguage())
.subscribeOn(getSchedulerProvider().io())
.observeOn(getSchedulerProvider().ui())
.subscribe(detailResponse -> {
setUpData(detailResponse);
getNavigator().ShowProgressDialog(false);
}, throwable -> {
getNavigator().ShowProgressDialog(false);
}));
}
}
private void setUpData(DetailResponse detailResponse) {
if (detailResponse.getOriginal_name() != null) {
originalName.set(detailResponse.getOriginal_name());
} else if (detailResponse.getOriginal_title() != null) {
originalName.set(detailResponse.getOriginal_title());
} else {
}
if (detailResponse.getFirst_air_date() != null) {
releaseDate.set(detailResponse.getFirst_air_date());
} else {
releaseDate.set(detailResponse.getRelease_date());
}
if (!detailResponse.getOverview().equals("")) {
overview.set(detailResponse.getOverview());
} else {
overview.set(getNavigator().noDesc());
}
posterPath.set(String.valueOf(detailResponse.getPoster_path()));
voteAverage.set(String.valueOf(detailResponse.getVote_average()));
String genres = "";
for (int i = 0; i < detailResponse.getGenreList().size(); i++) {
genres = genres + detailResponse.getGenreList().get(i).getName();
if (i != detailResponse.getGenreList().size() - 1) {
genres = genres + ", ";
}
}
genreMovie.set(genres);
}
public ObservableField<String> getOriginalName() {
return originalName;
}
public ObservableField<String> getReleaseDate() {
return releaseDate;
}
public ObservableField<String> getOverview() {
return overview;
}
public ObservableField<String> getGenreMovie() {
return genreMovie;
}
public ObservableField<String> getPosterPath() {
return posterPath;
}
public ObservableField<String> getVoteAverage() {
return voteAverage;
}
}
and this is my DetailResponse Class :
public class DetailResponse {
#SerializedName("original_name")
private String original_name ;
#SerializedName("original_title")
private String original_title ;
#SerializedName("release_date")
private String release_date ;
#SerializedName("first_air_date")
private String first_air_date ;
#SerializedName("vote_average")
private Double vote_average ;
#SerializedName("overview")
private String overview ;
#SerializedName("poster_path")
private String poster_path;
#SerializedName("genres")
private List<Genre> genreList;
public String getOriginal_name() {
return original_name;
}
public String getOriginal_title() {
return original_title;
}
public String getRelease_date() {
return release_date;
}
public String getFirst_air_date() {
return first_air_date;
}
public Double getVote_average() {
return vote_average;
}
public String getOverview() {
return overview;
}
public String getPoster_path() {
return poster_path;
}
public List<Genre> getGenreList() {
return genreList;
}
public static class Genre{
#SerializedName("name")
private String name ;
public String getName() {
return name;
}
}
}
and last one, here how I try to get data in my UI using databinding, this is my layout :
<?xml version="1.0" encoding="utf-8"?>
<layout 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"
tools:context=".ui.detail.DetailActivity">
<data>
<import type="android.view.View" />
<variable
name="viewModel"
type="id.dicoding.eriza.moviecatalogue.ui.detail.DetailViewModel" />
</data>
<androidx.core.widget.NestedScrollView
android:id="#+id/nestedScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:animateLayoutChanges="true">
<com.github.florent37.shapeofview.shapes.ArcView
android:id="#+id/shape_header"
android:layout_width="match_parent"
android:layout_height="#dimen/size300dp"
android:alpha="0.7"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:shape_arc_cropDirection="outside"
app:shape_arc_height="#dimen/size30dp"
app:shape_arc_position="bottom">
<com.flaviofaria.kenburnsview.KenBurnsView
android:id="#+id/image_header"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="#drawable/poster_avengerinfinity"
app:imageDetailUrl="#{viewModel.posterPath}"
android:tint="#6F000000" />
</com.github.florent37.shapeofview.shapes.ArcView>
<com.github.florent37.shapeofview.shapes.RoundRectView
android:id="#+id/shape_poster"
android:layout_width="#dimen/size150dp"
android:layout_height="#dimen/size200dp"
android:layout_marginTop="#dimen/margin250dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/shape_header"
app:shape_roundRect_bottomLeftRadius="#dimen/corner10dp"
app:shape_roundRect_bottomRightRadius="#dimen/corner10dp"
app:shape_roundRect_topLeftRadius="#dimen/corner10dp"
app:shape_roundRect_topRightRadius="#dimen/corner10dp">
<ImageView
android:id="#+id/image_poster"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="#string/hint_poster"
android:scaleType="fitXY"
app:imageDetailUrl="#{viewModel.posterPath}"
android:src="#drawable/poster_avengerinfinity" />
</com.github.florent37.shapeofview.shapes.RoundRectView>
<TextView
android:id="#+id/text_title"
style="#style/FontText.Title.Detail"
android:layout_marginTop="#dimen/margin15dp"
android:textSize="#dimen/font_large_size"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/shape_poster"
android:text="#{viewModel.originalName}"
tools:text="#string/hint_title" />
<TextView
android:id="#+id/text_title_release"
style="#style/FontText"
android:layout_marginTop="#dimen/margin10dp"
android:text="#string/text_release"
app:layout_constraintEnd_toStartOf="#+id/guideline"
android:visibility="#{viewModel.isConnected ? View.VISIBLE : View.GONE}"
app:layout_constraintTop_toBottomOf="#+id/text_title" />
<TextView
android:id="#+id/text_release"
style="#style/FontText"
android:layout_marginStart="#dimen/margin2dp"
android:layout_marginTop="#dimen/margin10dp"
android:text="#{viewModel.releaseDate}"
android:visibility="#{viewModel.isConnected ? View.VISIBLE : View.GONE}"
app:layout_constraintStart_toEndOf="#+id/text_title_release"
app:layout_constraintTop_toBottomOf="#+id/text_title"
tools:text="#string/hint_release" />
<TextView
android:id="#+id/text_genres"
style="#style/FontText.Normal"
android:layout_marginStart="#dimen/margin15dp"
android:layout_marginTop="#dimen/margin10dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/text_release"
android:text="#{viewModel.genreMovie}"
tools:text="#string/hint_genres" />
<RatingBar
android:id="#+id/rating_bar"
android:layout_width="wrap_content"
android:layout_height="45dp"
android:layout_marginStart="#dimen/margin15dp"
android:layout_marginTop="#dimen/margin5dp"
android:isIndicator="true"
android:numStars="5"
android:rating="3.8"
android:stepSize="0.1"
android:visibility="#{viewModel.isConnected ? View.VISIBLE : View.GONE}"
app:layout_constraintStart_toStartOf="parent"
app:ratingBar="#{viewModel.voteAverage}"
app:layout_constraintTop_toBottomOf="#+id/text_genres" />
<TextView
android:id="#+id/text_rating"
style="#style/FontText.Rating.Orange"
android:layout_marginStart="#dimen/margin5dp"
app:layout_constraintRight_toLeftOf="parent"
app:layout_constraintStart_toEndOf="#+id/rating_bar"
app:layout_constraintTop_toBottomOf="#+id/text_genres"
android:text="#{viewModel.voteAverage}"
tools:text="#string/hit_rating" />
<TextView
android:id="#+id/text_default_rating"
style="#style/FontText.Rating"
android:textStyle="normal"
android:visibility="#{viewModel.isConnected ? View.VISIBLE : View.GONE}"
app:layout_constraintRight_toLeftOf="parent"
app:layout_constraintStart_toEndOf="#+id/text_rating"
app:layout_constraintTop_toBottomOf="#+id/text_genres"
android:text="#string/hint_default_rating" />
<TextView
android:id="#+id/text_desc"
style="#style/FontText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/margin15dp"
android:layout_marginTop="#dimen/margin25dp"
android:layout_marginEnd="#dimen/margin15dp"
android:paddingBottom="#dimen/padding100dp"
app:layout_constraintTop_toBottomOf="#+id/rating_bar"
android:text="#{viewModel.overview}"
tools:text="#string/hint_desc" />
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</layout>
I think ViewModelshould manages UI that related data in Activity lifecycle, and tt allows to survive configuration changes in the Application, but in my case, the data is survive, but when I check on my logcat the fetchDetail() in DetailViewModel class is always call when screen rotation, and my ImageView is also refresh when I rotate my screen, so I think the viewModel not manage my UI when screen rotation. is there any problem with my code?
hope anybody can help me to show me where is my fault and what I must do. Thank you very much.
I'm new in android studio and currently creating an app which will retrieve data from existing db of sqlite. based on what I'd found is to create a layout file (not by creating new empty activity) to design on how the display the data. But in the layout, I want the button to open new activity, but somehow it didn't and I didn't found any solution so far. and the image also didn't appeared. This is the code:
DataPOI.java
public class DataPOI {
private int id;
private String category;
private String name;
private String hour;
private String phone_number;
private String address;
private String website;
private int fee_adult_standard;
private int fee_child_standard;
private int fee_senior_standard;
private int fee_adult_MyKad;
private int fee_child_MyKid;
private int fee_senior_MyKad;
private int fee_student_standard;
private int fee_student_MyKad;
private String description;
private byte[] photo;
private String coordinate;
private String door;
private String parking1;
private String parking2;
public DataPOI(int id, String category, String name, String hour, String phone_number,
String address, String website, int fee_adult_standard, int fee_child_standard,
int fee_senior_standard, int fee_adult_MyKad, int fee_child_MyKid,
int fee_senior_MyKad, int fee_student_standard, int fee_student_MyKad,
String description, byte[] photo, String coordinate, String door,
String parking1, String parking2) {
this.id = id;
this.category = category;
this.name = name;
this.hour = hour;
this.phone_number = phone_number;
this.address = address;
this.website = website;
this.fee_adult_standard = fee_adult_standard;
this.fee_child_standard = fee_child_standard;
this.fee_senior_standard = fee_senior_standard;
this.fee_adult_MyKad = fee_adult_MyKad;
this.fee_child_MyKid = fee_child_MyKid;
this.fee_senior_MyKad = fee_senior_MyKad;
this.fee_student_standard = fee_student_standard;
this.fee_student_MyKad = fee_student_MyKad;
this.description = description;
this.photo = photo;
this.coordinate = coordinate;
this.door = door;
this.parking1 = parking1;
this.parking2 = parking2;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getHour() {
return hour;
}
public void setHour(String hour) {
this.hour = hour;
}
public String getPhone_number() {
return phone_number;
}
public void setPhone_number(String phone_number) {
this.phone_number = phone_number;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getWebsite() {
return website;
}
public void setWebsite(String website) {
this.website = website;
}
public int getFee_adult_standard() {
return fee_adult_standard;
}
public void setFee_adult_standard(int fee_adult_standard) {
this.fee_adult_standard = fee_adult_standard;
}
public int getFee_child_standard() {
return fee_child_standard;
}
public void setFee_child_standard(int fee_child_standard) {
this.fee_child_standard = fee_child_standard;
}
public int getFee_senior_standard() {
return fee_senior_standard;
}
public void setFee_senior_standard(int fee_senior_standard) {
this.fee_senior_standard = fee_senior_standard;
}
public int getFee_adult_MyKad() {
return fee_adult_MyKad;
}
public void setFee_adult_MyKad(int fee_adult_MyKad) {
this.fee_adult_MyKad = fee_adult_MyKad;
}
public int getFee_child_MyKid() {
return fee_child_MyKid;
}
public void setFee_child_MyKid(int fee_child_MyKid) {
this.fee_child_MyKid = fee_child_MyKid;
}
public int getFee_senior_MyKad() {
return fee_senior_MyKad;
}
public void setFee_senior_MyKad(int fee_senior_MyKad) {
this.fee_senior_MyKad = fee_senior_MyKad;
}
public int getFee_student_standard() {
return fee_student_standard;
}
public void setFee_student_standard(int fee_student_standard) {
this.fee_student_standard = fee_student_standard;
}
public int getFee_student_MyKad() {
return fee_student_MyKad;
}
public void setFee_student_MyKad(int fee_student_MyKad) {
this.fee_student_MyKad = fee_student_MyKad;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public byte[] getPhoto() {
return photo;
}
public void setPhoto(byte[] photo) {
this.photo = photo;
}
public String getCoordinate() {
return coordinate;
}
public void setCoordinate(String coordinate) {
this.coordinate = coordinate;
}
public String getDoor() {
return door;
}
public void setDoor(String door) {
this.door = door;
}
public String getParking1() {
return parking1;
}
public void setParking1(String parking1) {
this.parking1 = parking1;
}
public String getParking2() {
return parking2;
}
public void setParking2(String parking2) {
this.parking2 = parking2;
}
}
ListPOIadapter.java
public class ListPOIadapter extends BaseAdapter {
private Context mContext;
private List<DataPOI> mPOIList;
public ListPOIadapter(Context mContext, List<DataPOI> mPOIList) {
this.mContext = mContext;
this.mPOIList = mPOIList;
}
#Override
public int getCount() {
return mPOIList.size();
}
#Override
public Object getItem(int i) {
return mPOIList.get(i);
}
#Override
public long getItemId(int i) {
return mPOIList.get(i).getId();
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
View v = View.inflate(mContext, R.layout.data_layout, null);
//edit below this
ImageView myPhoto = (ImageView)v.findViewById(R.id.imageView);
TextView myName = (TextView)v.findViewById(R.id.name);
TextView myHour = (TextView)v.findViewById(R.id.operational_hour);
TextView myContact = (TextView)v.findViewById(R.id.contact_number);
TextView myWebsite = (TextView)v.findViewById(R.id.website);
TextView myAddress = (TextView)v.findViewById(R.id.address);
//myPhoto.setI(mPOIList.get(i).getPhoto());
myName.setText(mPOIList.get(i).getName());
myHour.setText(mPOIList.get(i).getHour());
myContact.setText(mPOIList.get(i).getPhone_number());
myWebsite.setText(mPOIList.get(i).getWebsite());
myAddress.setText(mPOIList.get(i).getAddress());
return v;
}
}
AmusementPark.java
public class AmusementPark extends AppCompatActivity {
private ListView lvPOI;
private ListPOIadapter adapter;
private List<DataPOI> mPOIList;
private AmusementPark_Helper mDBHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_amusement_park);
lvPOI = (ListView)findViewById(R.id.listview_product);
mDBHelper = new AmusementPark_Helper(this);
//Check existis database
File database = getApplicationContext().getDatabasePath(AmusementPark_Helper.DBNAME);
if(false == database.exists()) {
mDBHelper.getReadableDatabase();
//Copy db
if(copyDatabase(this)) {
Toast.makeText(this, "Copy database success", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(this, "Copy database error", Toast.LENGTH_SHORT).show();
return;
}
}
//Get product list in db when db exists
mPOIList = mDBHelper.getListPOI();
//Init adapter
adapter = new ListPOIadapter(this, mPOIList);
//Set adapter for listview
lvPOI.setAdapter(adapter);
}
private boolean copyDatabase (Context context) {
try {
InputStream inputStream = context.getAssets().open(AmusementPark_Helper.DBNAME);
String outFileName = AmusementPark_Helper.DBLOCATION + AmusementPark_Helper.DBNAME;
OutputStream outputStream = new FileOutputStream(outFileName);
byte[]buff = new byte[1024];
int length = 0;
while ((length = inputStream.read(buff)) > 0) {
outputStream.write(buff, 0, length);
}
outputStream.flush();
outputStream.close();
Log.v("Amusement Park", "DB copied");
return true;
}
catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
AmusementPark_Helper.java
public class AmusementPark_Helper extends SQLiteOpenHelper {
public static final String DBNAME = "placeofinterest.sqlite";
public static final String DBLOCATION = "/data/data/com.example.lenovo.welcome.ListHelper";
private Context mContext;
private SQLiteDatabase mDatabase;
public AmusementPark_Helper (Context context) {
super(context, DBNAME, null, 1);
this.mContext = context;
}
#Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
}
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
public void openDatabase() {
String dbPath = mContext.getDatabasePath(DBNAME).getPath();
if(mDatabase != null && mDatabase.isOpen()) {
return;
}
mDatabase = SQLiteDatabase.openDatabase(dbPath, null, SQLiteDatabase.OPEN_READWRITE);
}
public void closeDatabase() {
if(mDatabase != null) {
mDatabase.close();
}
}
public List<DataPOI> getListPOI() {
DataPOI placeofinterest = null;
List<DataPOI> poiList = new ArrayList<>();
openDatabase();
Cursor cursor = mDatabase.rawQuery("SELECT * FROM amusement_park", null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
//below is depends on data type of each column
placeofinterest = new DataPOI(
cursor.getInt(0), cursor.getString(1), cursor.getString(2),
cursor.getString(3), cursor.getString(4), cursor.getString(5),
cursor.getString(6), cursor.getInt(7), cursor.getInt(8),
cursor.getInt(9), cursor.getInt(10), cursor.getInt(11),
cursor.getInt(12), cursor.getInt(13), cursor.getInt(14),
cursor.getString(15), cursor.getBlob(16), cursor.getString(17),
cursor.getString(18), cursor.getString(19), cursor.getString(20));
poiList.add(placeofinterest);
cursor.moveToNext();
}
cursor.close();
closeDatabase();
return poiList;
}
}
data_layout.xml (created not by using "create new empty activity")
<RelativeLayout
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="210dp"
android:background="#89cff0">
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
app:srcCompat="#mipmap/ic_launcher_round" />
<TextView
android:id="#+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/imageView"
android:text="Name of POI"
android:textColor="#000"
android:textSize="19sp" />
<TextView
android:id="#+id/operational_hour"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/name"
android:layout_toRightOf="#id/imageView"
android:text="Operational Hours"
android:textColor="#000"
android:textSize="15sp" />
<TextView
android:id="#+id/contact_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/operational_hour"
android:layout_toRightOf="#id/imageView"
android:text="Contact Number"
android:textColor="#000"
android:textSize="15sp" />
<TextView
android:id="#+id/website"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/contact_number"
android:layout_toRightOf="#id/imageView"
android:clickable="true"
android:text="Website"
android:autoLink="web"
android:textColor="#000"
android:textSize="15sp" />
<TextView
android:id="#+id/address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/website"
android:layout_toRightOf="#id/imageView"
android:clickable="true"
android:text="Address"
android:textColor="#000"
android:textSize="15sp" />
<Button
android:id="#+id/button_description"
android:layout_width="140dp"
android:layout_height="wrap_content"
android:layout_below="#id/address"
android:layout_marginBottom="5dp"
android:layout_marginRight="5dp"
android:layout_toRightOf="#id/imageView"
android:layout_weight="1"
android:background="#drawable/mybutton"
android:text="Description"
android:textColor="#000" />
<Button
android:id="#+id/button_entrance_fee"
android:layout_width="140dp"
android:layout_height="wrap_content"
android:layout_below="#id/address"
android:layout_marginBottom="5dp"
android:layout_marginRight="5dp"
android:layout_toRightOf="#id/button_description"
android:layout_weight="1"
android:background="#drawable/mybutton"
android:text="Entrance Fee"
android:textColor="#000" />
<Button
android:id="#+id/button_nearest_me"
android:layout_width="140dp"
android:layout_height="wrap_content"
android:layout_below="#id/button_entrance_fee"
android:layout_marginBottom="5dp"
android:layout_marginRight="5dp"
android:layout_toRightOf="#id/imageView"
android:layout_weight="1"
android:background="#drawable/mybutton"
android:text="Nearest Me"
android:textColor="#000" />
<Button
android:id="#+id/button_take_me_there"
android:layout_width="140dp"
android:layout_height="wrap_content"
android:layout_below="#id/button_entrance_fee"
android:layout_marginBottom="5dp"
android:layout_marginRight="5dp"
android:layout_toRightOf="#id/button_nearest_me"
android:layout_weight="1"
android:background="#drawable/mybutton"
android:text="Take Me There"
android:textColor="#000" />
</RelativeLayout>
So, how to open new activity from a button which as no .java? I tried to create a new activity and copy paste from the data_layout.xml but it still not working. I hope my explanation is quite clear. and please help me. Thank you.
In your AmusementPark.java file, change
if(false == database.exists()) {
to
if(database.exists == false) {
Also verify the paths are correct. See this very similar article: How do I get a button to open another activity in Android Studio?
Code taken from article:
Manifest file
<activity
android:name="MyOtherActivity"
android:label="#string/app_name">
</activity>
Activity.java file
Button btn = (Button)findViewById(R.id.open_activity_button);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, MyOtherActivity.class));
}
});
private class getArticles extends AsyncTask<Void, Void, Void> {
String url;
getArticles(String paramUrl) {
this.url = paramUrl;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
mProgressDialog = new ProgressDialog(App.this);
mProgressDialog.setMessage("Učitavanje artikala...");
mProgressDialog.setIndeterminate(false);
mProgressDialog.setCancelable(false);
mProgressDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
arraylist = new ArrayList<>();
try {
Document document = Jsoup.connect(url).get();
Elements els = document.select("ul.category3 > li");
for (Element el : els) {
HashMap<String, String> map = new HashMap<>();
Elements slika = el.select("div.category3-image > a > img");
Elements naslov = el.select("div.category3-text > a.main-headline");
Element datum_noformat = el.select("div.category3-text > div.headlines-info > ul.headlines-info > li").first();
Element datum = datum_noformat.html(datum_noformat.html().replaceAll("Posted ", ""));
Elements desc = el.select("div.category3-text > p");
Elements link = el.select("div.category3-text > a.main-headline");
Element br_kom = el.select("div.category3-text > div.headlines-info > ul.headlines-info > li.comments-icon").first();
map.put("naslov", naslov.text());
map.put("datum", datum.text());
map.put("desc", desc.text());
map.put("ikona", slika.attr("src"));
map.put("link", link.attr("abs:href"));
map.put("brkom", br_kom.text());
arraylist.add(map);
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
listview = (ListView) findViewById(R.id.listview);
adapter = new ArtikliAdapter(App.this, arraylist);
listview.setAdapter(adapter);
mProgressDialog.dismiss();
}
I searched for a lot of codes for onlistview scrolling, but didn't know how to implement it. The problem is, when I call my asynctask, I have an url param,
like new getArticles("http://example.com").execute();
I want to implement an onscrolllistener, but it goes like this, my param is usually set to: http://www.example.com/category/categoryname/, so the second page goes like http://www.example.com/category/categoryname/page/2/, the third one goes http://www.example.com/category/categoryname/page/3/ and so on. Each page has got 7 items that need to be parsed.
How could I implement onscrolllistener, because of the url param?
Thanks in advance.
Base on this link, I have written following solution to add elements ( 30 elements at a time, i.e page size = 30) to listview asynchronously.
Create a class named EndlessListView as follows:
public class EndlessListView extends ListView implements OnScrollListener {
private View footer;
private boolean isLoading;
private EndlessListener listener;// listner
private EndlessAdapter endlessAdapter;// adapter.
private int maxNoOfElement;
public EndlessListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.setOnScrollListener(this);
}
public EndlessListView(Context context, AttributeSet attrs) {
super(context, attrs);
this.setOnScrollListener(this);
}
public EndlessListView(Context context) {
super(context);
this.setOnScrollListener(this);
}
public void setListener(EndlessListener listener) {
this.listener = listener;
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (getAdapter() == null)
return;
if (getAdapter().getCount() == 0 || getAdapter().getCount() <= 5)
return;
int l = visibleItemCount + firstVisibleItem;
if (l >= totalItemCount && !isLoading) {
// It is time to add new data. We call the listener
Log.e("LOAD", "DATA");
isLoading = true;
listener.loadData();
}
}
public void setMaxElemnt(int maxNoOfElement) {
this.maxNoOfElement = maxNoOfElement;
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
public void setLoadingView(int resId) {
LayoutInflater inflater = (LayoutInflater) super.getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
footer = (View) inflater.inflate(resId, null);
this.addFooterView(footer);
}
public void setAdapter(EndlessAdapter adapter) {
super.setAdapter(adapter);
this.endlessAdapter = adapter;
}
public void addNewData(List<Integer> data) {
endlessAdapter.setData(data);
endlessAdapter.notifyDataSetChanged();
isLoading = false;
}
public static interface EndlessListener {
public void loadData();
}
}
After this we have to create the adapter for it,called
EndlessAdapter
public class EndlessAdapter extends BaseAdapter {
private List<Integer> mIntegers;
private Context context;
public EndlessAdapter(Context context) {
this.context = context;
}
public void setData(List<Integer> mIntegers) {
this.mIntegers = mIntegers;
}
#Override
public int getCount() {
if (mIntegers == null)
return 0;
return mIntegers.size();
}
#Override
public Integer getItem(int index) {
if (mIntegers == null) {
return null;
} else {
return mIntegers.get(index);
}
}
#Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return 0;
}
class ViewHolder {
TextView textView;
}
#Override
public View getView(int index, View view, ViewGroup viewGroup) {
ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
view = ((LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE))
.inflate(R.layout.rows, viewGroup, false);
holder.textView = (TextView) view.findViewById(R.id.mtext);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
holder.textView.setText(getItem(index) + "");
return view;
}
}
Now in xml of the activity we could use EndlessListView(in com.example.stackoverflow package) as follows :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.stackoverflow.EndlessListView
android:id="#+id/endlessListView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
After this step we need to make following change in the MainActivity
public class MainActivity extends Activity implements EndlessListener {
private EndlessAdapter adapter;
private EndlessListView endlessListView;
private List<Integer> data;
private int gStartIndex = 30;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
endlessListView = (EndlessListView) findViewById(R.id.endlessListView);
adapter = new EndlessAdapter(this);
data = new ArrayList<Integer>();
endlessListView.setLoadingView(R.layout.footer);
// endlessListView.showFooter();
endlessListView.setListener(this);
endlessListView.setAdapter(adapter);
gStartIndex = 0;
fillData(gStartIndex);
}
private void fillData(int startIndex) {
new AsyncLoadData().execute(startIndex);
}
#Override
public void loadData() {
fillData(gStartIndex);
}
private class AsyncLoadData extends AsyncTask<Integer, Integer, Void> {
#Override
protected Void doInBackground(Integer... params) {
int gendIndex = params[0] + 30;
gStartIndex = gendIndex;
/***
* Here you could add your n/w code. To simulate the n/w comm. i am
* adding elements to list and making it sleep for few sec.
* */
for (int i = params[0]; i < gendIndex; i++) {
publishProgress(i);
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
data.add(values[0]);
}
#Override
protected void onPostExecute(Void result) {
endlessListView.addNewData(data);
}
}
}
This custom ScrollListView that I just found has OnBottomReachedListener which you can implement from your Activity or Fragment and receive events when user hits the bottom of the page. You would also need to track the current page and when bottom is hit to download the next page. The latest data should be added to your existing ArrayList and you should call notifyDataSetChanged() on your adapter so ListView can render the new data. You don't have to create new adapter, you just need to update the data source which is your ArrayList.
If you support orientation change you would must to save in onSaveInstanceState() your current page number so when Activity or Fragment is recreated it can continue from correct page. And you would have to keep the ArrayList data source safe of configuration changes because you don't want to downloaded it again. I would suggest using the Fragment with setRetainInstance() set to true to persist ArrayList.
Here is my custom code for keeping data around using RetainFragment:
/**
* A simple non-UI Fragment that stores a single Object
* and is retained over configuration changes.
*/
public class RetainFragment<E extends Object> extends Fragment {
/** Object for retaining. */
private E mObject;
/**
* Empty constructor as per the Fragment documentation
*/
public RetainFragment() {}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Make sure this Fragment is retained over a configuration change
setRetainInstance(true);
}
/**
* Store a single object in this Fragment.
*
* #param object The object to store
*/
public void setObject(E object) {
mObject = object;
}
/**
* Get the stored object.
*
* #return The stored object
*/
public E getObject() {
return mObject;
}
}
Example of RetainFragment usage in your Activity:
FragmentManager fm = getFragmentManager();
mRetainFragment = (RetainFragment<ArrayList>) fm.findFragmentByTag(RETAIN_FRAG);
if (mRetainFragment == null) {
mRetainFragment = new RetainFragment<>();
mRetainFragment.setObject(new ArrayList());
fm.beginTransaction().add(mRetainFragment, RETAIN_FRAG).commit();
}
ArrayList yourArrayList = mRetainFragment.getObject();
// Now your ArrayList is saved accrossed configuration changes
here what you want fist add onscrolllistner to listview
boolean loading_flage = false;
yourlistview.setOnScrollListener(new OnScrollListener() {
#Override
public void onScrollStateChanged(
AbsListView view,
int scrollState) {
// TODO Auto-generated method stub
}
#Override
public void onScroll(AbsListView view,
int firstVisibleItem,
int visibleItemCount,
int totalItemCount) {
final int lastItem = firstVisibleItem
+ visibleItemCount;
if ((lastItem == totalItemCount)
& loading_flage == false) {
//this to prevent the list to make more than one request in time
loading_flage = true;
//you can put the index for your next page here
loadMore(int page);
}
}
});
and then in loading more after loading the page set the loading with false and parse the data add it to the data that you aleardy have
//notify the adapter
adapter.notifyDataSetChanged();
loading_flage = false;
You can achieve by adding the scrolllistener on listview and check condition if list last visible item is last in ArrayList then call the asynctask with incremented page number and update the listview,mean while add the view on listview and after getting the result from server remove the loading more view from the listview like this -
AndroidListViewLoadMoreActivity.java
public class AndroidListViewLoadMoreActivity extends Activity {
ArrayList<Country> countryList;
MyCustomAdapter dataAdapter = null;
int page = 0;
boolean loadingMore = false;
View loadMoreView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ListView listView = (ListView) findViewById(R.id.listView1);
loadMoreView = ((LayoutInflater)this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE))
.inflate(R.layout.loadmore, null, false);
listView.addFooterView(loadMoreView);
//create an ArrayAdaptar from the String Array
countryList = new ArrayList<Country>();
dataAdapter = new MyCustomAdapter(this,
R.layout.country_info, countryList);
listView.setAdapter(dataAdapter);
//enables filtering for the contents of the given ListView
listView.setTextFilterEnabled(true);
listView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// When clicked, show a toast with the TextView text
Country country = (Country) parent.getItemAtPosition(position);
Toast.makeText(getApplicationContext(),
country.getCode(), Toast.LENGTH_SHORT).show();
}
});
listView.setOnScrollListener(new OnScrollListener(){
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
int lastInScreen = firstVisibleItem + visibleItemCount;
if((lastInScreen == totalItemCount) && !(loadingMore)){
String url = "http://10.0.2.2:8080/CountryWebService" +
"/CountryServlet";
grabURL(url);
}
}
});
String url = "http://example.com";
grabURL(url);
}
public void grabURL(String url) {
Log.v("Android Spinner JSON Data Activity", url);
new GrabURL().execute(url);
}
private class GrabURL extends AsyncTask<String, Void, String> {
private static final int REGISTRATION_TIMEOUT = 3 * 1000;
private static final int WAIT_TIMEOUT = 30 * 1000;
private final HttpClient httpclient = new DefaultHttpClient();
final HttpParams params = httpclient.getParams();
HttpResponse response;
private String content = null;
private boolean error = false;
private ProgressDialog dialog =
new ProgressDialog(AndroidListViewLoadMoreActivity.this);
protected void onPreExecute() {
dialog.setMessage("Getting your data... Please wait...");
dialog.show();
}
protected String doInBackground(String... urls) {
String URL = null;
loadingMore = true;
try {
URL = urls[0];
HttpConnectionParams.setConnectionTimeout(params, REGISTRATION_TIMEOUT);
HttpConnectionParams.setSoTimeout(params, WAIT_TIMEOUT);
ConnManagerParams.setTimeout(params, WAIT_TIMEOUT);
HttpPost httpPost = new HttpPost(URL);
//add name value pair for the country code
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("page",String.valueOf(page)));
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
response = httpclient.execute(httpPost);
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() == HttpStatus.SC_OK){
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
out.close();
content = out.toString();
} else{
//Closes the connection.
Log.w("HTTP1:",statusLine.getReasonPhrase());
response.getEntity().getContent().close();
throw new IOException(statusLine.getReasonPhrase());
}
} catch (ClientProtocolException e) {
Log.w("HTTP2:",e );
content = e.getMessage();
error = true;
cancel(true);
} catch (IOException e) {
Log.w("HTTP3:",e );
content = e.getMessage();
error = true;
cancel(true);
}catch (Exception e) {
Log.w("HTTP4:",e );
content = e.getMessage();
error = true;
cancel(true);
}
return content;
}
protected void onCancelled() {
dialog.dismiss();
Toast toast = Toast.makeText(AndroidListViewLoadMoreActivity.this,
"Error connecting to Server", Toast.LENGTH_LONG);
toast.setGravity(Gravity.TOP, 25, 400);
toast.show();
}
protected void onPostExecute(String content) {
dialog.dismiss();
Toast toast;
if (error) {
toast = Toast.makeText(AndroidListViewLoadMoreActivity.this,
content, Toast.LENGTH_LONG);
toast.setGravity(Gravity.TOP, 25, 400);
toast.show();
} else {
displayCountryList(content);
}
}
}
private void displayCountryList(String response){
JSONObject responseObj = null;
try {
Gson gson = new Gson();
responseObj = new JSONObject(response);
JSONArray countryListObj = responseObj.getJSONArray("countryList");
//countryList = new ArrayList<Country>();
if(countryListObj.length() == 0){
ListView listView = (ListView) findViewById(R.id.listView1);
listView.removeFooterView(loadMoreView);
}
else {
for (int i=0; i<countryListObj.length(); i++){
//get the country information JSON object
String countryInfo = countryListObj.getJSONObject(i).toString();
//create java object from the JSON object
Country country = gson.fromJson(countryInfo, Country.class);
//add to country array list
countryList.add(country);
dataAdapter.add(country);
}
page++;
dataAdapter.notifyDataSetChanged();
loadingMore = false;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
Make MyCustomAdapter.java as adapter
private class MyCustomAdapter extends ArrayAdapter<Country> {
private ArrayList<Country> countryList;
public MyCustomAdapter(Context context, int textViewResourceId,
ArrayList<Country> countryList) {
super(context, textViewResourceId, countryList);
this.countryList = new ArrayList<Country>();
this.countryList.addAll(countryList);
}
private class ViewHolder {
TextView code;
TextView name;
TextView continent;
TextView region;
}
public void add(Country country){
Log.v("AddView", country.getCode());
this.countryList.add(country);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
Log.v("ConvertView", String.valueOf(position));
if (convertView == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.country_info, null);
holder = new ViewHolder();
holder.code = (TextView) convertView.findViewById(R.id.code);
holder.name = (TextView) convertView.findViewById(R.id.name);
holder.continent = (TextView) convertView.findViewById(R.id.continent);
holder.region = (TextView) convertView.findViewById(R.id.region);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Country country = this.countryList.get(position);
holder.code.setText(country.getCode());
holder.name.setText(country.getName());
holder.continent.setText(country.getContinent());
holder.region.setText(country.getRegion());
return convertView;
}
}
}
Create Country.Java as pojo -
public class Country {
String code = null;
String name = null;
String continent = null;
String region = null;
Double lifeExpectancy = null;
Double gnp = null;
Double surfaceArea = null;
int population = 0;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContinent() {
return continent;
}
public void setContinent(String continent) {
this.continent = continent;
}
public String getRegion() {
return region;
}
public void setRegion(String region) {
this.region = region;
}
public Double getLifeExpectancy() {
return lifeExpectancy;
}
public void setLifeExpectancy(Double lifeExpectancy) {
this.lifeExpectancy = lifeExpectancy;
}
public Double getGnp() {
return gnp;
}
public void setGnp(Double gnp) {
this.gnp = gnp;
}
public Double getSurfaceArea() {
return surfaceArea;
}
public void setSurfaceArea(Double surfaceArea) {
this.surfaceArea = surfaceArea;
}
public int getPopulation() {
return population;
}
public void setPopulation(int population) {
this.population = population;
}
}
Create main.xml for main layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical">
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:padding="10dp"
android:text="#string/some_text" android:textSize="20sp" />
<ListView android:id="#+id/listView1" android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
Create country_info.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="6dip" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="Code: "
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView1"
android:layout_below="#+id/textView1"
android:text="Name: "
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView2"
android:layout_below="#+id/textView2"
android:text="Continent: "
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView3"
android:layout_below="#+id/textView3"
android:text="Region: "
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/continent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/textView3"
android:layout_alignBottom="#+id/textView3"
android:layout_toRightOf="#+id/textView3"
android:text="TextView" />
<TextView
android:id="#+id/region"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/textView4"
android:layout_alignBottom="#+id/textView4"
android:layout_alignLeft="#+id/continent"
android:text="TextView" />
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/textView3"
android:layout_toRightOf="#+id/textView3"
android:text="TextView" />
<TextView
android:id="#+id/code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/textView2"
android:layout_alignLeft="#+id/name"
android:text="TextView" />
</RelativeLayout>
Footer View Text - loadmore.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:gravity="center_horizontal"
android:padding="3dp"
android:layout_height="fill_parent">
<TextView
android:id="#id/android:empty"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:gravity="center"
android:padding="5dp"
android:text="Loading more data..."/>
</LinearLayout>
Don't forget to mention internet permission with -
<uses-permission android:name="android.permission.INTERNET" />
First, you need a OnScrollListener method like this:
private OnScrollListener onScrollListener() {
return new OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
int threshold = 1;
int count = listView.getCount();
if (scrollState == SCROLL_STATE_IDLE) {
if (listView.getLastVisiblePosition() >= count - threshold && pageCount < 2) {
Log.i(TAG, "loading more data");
// Execute LoadMoreDataTask AsyncTask
//It reached ListView bottom
getDataFromUrl(url_page2);
}
}
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
}
};
}
set List View scroll listener by listView.setOnScrollListener(onScrollListener());
I have a full tutorial post HERE! You can visit it!