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.
Related
I'm trying to Retrieve data from Firebase database and storage into a RecyclerView and CardView , i don't get any error on the code but when i run the application nothing shows up and i get a message in the run like this (V/FA: Inactivity, disconnecting from the service
I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy#c2f66cf time:168073912
)
i have tried many solutions like this one here V/FA: Inactivity, disconnecting from the service
but it didn't workout with me
my photo folder in firebase database name /doctor_images
this is my class Doctor
public class Doctor {
private String doctor_ID;
private String doctor_Name;
private String doctor_Email;
private String doctor_Phone;
private String doctor_Speciality;
private int doctor_Rating;
private String doctor_Image_Url;
public String getDoctor_ID() {
return doctor_ID;
}
public void setDoctor_ID(String doctor_ID) {
this.doctor_ID = doctor_ID;
}
public String getDoctor_Name() {
return doctor_Name;
}
public void setDoctor_Name(String doctor_Name) {
this.doctor_Name = doctor_Name;
}
public String getDoctor_Email() {
return doctor_Email;
}
public void setDoctor_Email(String doctor_Email) {
this.doctor_Email = doctor_Email;
}
public String getDoctor_Phone() {
return doctor_Phone;
}
public void setDoctor_Phone(String doctor_Phone) {
this.doctor_Phone = doctor_Phone;
}
public String getDoctor_Speciality() {
return doctor_Speciality;
}
public void setDoctor_Speciality(String doctor_Speciality) {
this.doctor_Speciality = doctor_Speciality; }
public int getDoctor_Rating() {
return doctor_Rating;
}
public void setDoctor_Rating(int doctor_Rating) {
this.doctor_Rating = doctor_Rating;
}
public String getDoctor_Image_Url() {
return doctor_Image_Url;
}
public void setDoctor_Image_Url(String doctor_Image_Url) {
this.doctor_Image_Url = doctor_Image_Url; }
public Doctor() { }
public Doctor(String doctor_ID, String doctor_Name, String doctor_Email,
String doctor_Phone, String doctor_Speciality, int doctor_Rating, String
doctor_Image_Url) {
this.doctor_ID = doctor_ID;
this.doctor_Name = doctor_Name;
this.doctor_Email = doctor_Email;
this.doctor_Phone = doctor_Phone;
this.doctor_Speciality = doctor_Speciality;
this.doctor_Rating = doctor_Rating;
this.doctor_Image_Url = doctor_Image_Url; }}
and my Adapter code is this
public class DoctorAdapter extends RecyclerView.Adapter<DoctorAdapter.DoctorViewHolder> {
private Context mcontext;
private List<Doctor> mDoctor;
public DoctorAdapter (Context context , List<Doctor> doctors){
mcontext = context;
mDoctor = doctors; }
#NonNull
#Override
public DoctorViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(mcontext).inflate(R.layout.image_doctor,parent,false);
return new DoctorViewHolder(v); }
#Override
public void onBindViewHolder(#NonNull DoctorViewHolder holder, int position) {
Doctor doctorCurrent = mDoctor.get(position);
holder.txtNameDoctor.setText(doctorCurrent.getDoctor_Name());
holder.txtSpecialityDoctor.setText(doctorCurrent.getDoctor_Speciality());
Picasso.with(mcontext)
.load(doctorCurrent.getDoctor_Image_Url())
.fit()
.centerCrop()
.into(holder.imgDoctor); }
#Override
public int getItemCount() {
return mDoctor.size(); }
public class DoctorViewHolder extends RecyclerView.ViewHolder{
public TextView txtNameDoctor;
public TextView txtSpecialityDoctor;
public ImageView imgDoctor;
public DoctorViewHolder(#NonNull View itemView) {
super(itemView);
txtNameDoctor = itemView.findViewById(R.id.doctor_name_recycler_card);
txtSpecialityDoctor = itemView.findViewById(R.id.doctor_Speciality_recycler_card);
imgDoctor = itemView.findViewById(R.id.doctor_image_recycler_card); }
}
}
and my card Layout
<LinearLayout
android:id="#+id/container_all_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:padding="10dp"
android:background="#drawable/card_shape"
>
<ImageView
android:id="#+id/doctor_image_recycler_card"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_margin="5dp"/>
<LinearLayout
android:layout_marginTop="5dp"
android:id="#+id/container_text_card"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_marginTop="10dp"
android:id="#+id/doctor_name_recycler_card"
android:textAppearance="#style/TextAppearance.AppCompat.Large"
android:layout_width="230dp"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textColor="#ffffff" />
<TextView
android:id="#+id/doctor_Speciality_recycler_card"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:textSize="20dp" />
</LinearLayout>
</LinearLayout>
and this is my RecyclerView in my Layout
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycle_search_doctor"
android:layout_width="match_parent"
android:layout_height="match_parent" />
and this is my Activity java class
public class AllDoctorActivity extends AppCompatActivity {
private RecyclerView mRecyclerView ;
private DatabaseReference mdatabaseReference;
private DoctorAdapter mdoctorAdapter;
private List<Doctor> mdoctors;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_all_doctor);
mRecyclerView = findViewById(R.id.recycle_search_doctor);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mdoctors = new ArrayList<>();
mdatabaseReference = FirebaseDatabase.getInstance().getReference("doctors");
mdatabaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot postSnapShot : snapshot.getChildren()){
Doctor doctor = postSnapShot.getValue(Doctor.class);
mdoctors.add(doctor);
}
mdoctorAdapter = new DoctorAdapter(AllDoctorActivity.this,mdoctors);
mRecyclerView.setAdapter(mdoctorAdapter);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Toast.makeText(AllDoctorActivity.this, error.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
}
this is my doctor json code
i have added 2 doctors in 1 hospital and 1 doctor in another hospital
"doctors" : {
"-MEOD5GJqtMUR6V4XGbO" : {
"-MGmxz1j6vmSzK0DlExJ" : {
"doctor_Email" : "576",
"doctor_Image_Url" : "https://firebasestorage.googleapis.com/v0/b/my-appointment",
"doctor_Name" : "yyyy",
"doctor_Phone" : "756",
"doctor_Rating" : "3",
"doctor_Speciality" : "756"
},
"-MGmy0tSdXTq4X0Nhqpb" : {
"doctor_Email" : "576",
"doctor_Image_Url" : "https://firebasestorage.googleapis.com/v0/b/my-appointment",
"doctor_Name" : "yyyy",
"doctor_Phone" : "756",
"doctor_Rating" : "3",
"doctor_Speciality" : "756"
}
},
"-MGN5Lno-SA7b50ACOpK" : {
"-MGwJr8Z1GmVdNrYcMyA" : {
"doctor_Email" : "abdo53#gmail.com",
"doctor_Image_Url" : "https://firebasestorage.googleapis.com/v0/b/my-appointment",
"doctor_Name" : "محمد",
"doctor_Phone" : "56777747",
"doctor_Rating" : "1",
"doctor_Speciality" : "56777747"
}
}
},
and this is my hospital json code
"hospitals" : {
"-MEOD5GJqtMUR6V4XGbO" : {
"hospital_address" : "شارع بغداد",
"hospital_name" : "عبد القادر المتوكل",
"hospital_number" : "777777",
"hospital_phone" : "7777777",
"id" : "-MEOD5GJqtMUR6V4XGbO"
},
"-MGN5Lno-SA7b50ACOpK" : {
"hospital_address" : "شارع الزبيري",
"hospital_name" : "الجمهوري",
"hospital_number" : "555555",
"hospital_phone" : "77555555",
"id" : "-MGN5Lno-SA7b50ACOpK"
},
"-MGOHrjqhGZ8EjeGHPjW" : {
"hospital_address" : "الستين",
"hospital_name" : "ازال",
"hospital_number" : "88888",
"hospital_phone" : "888888",
"id" : "-MGOHrjqhGZ8EjeGHPjW"
}
}
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'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!
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;
}
}