I am trying to get the background to change on click after 500 ms. All it does right now is go black. It doesn't even show the view just a black screen. The list of colors comes from a database, the JSON data is parsed for the color value. I am using Android 6 API 23.
public class CycleColors extends AppCompatActivity {
private static final String TAG = CycleColors.class.getName();
static List<String> colorsList = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cycle_colors);
Button doneBtn = (Button)findViewById(R.id.btnDone);
doneBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
clickDoneButton();
}
});
getData();
Intent intent = getIntent();
new cycle(this).execute();
}
public void clickDoneButton()
{
finish();
}
class cycle extends AsyncTask<Void, Void, Void>
{
private Activity activity;
View view;
public cycle(Activity a)
{
activity = a;
view = activity.getWindow().getDecorView();
}
protected Void doInBackground(Void... param)
{
activity.runOnUiThread(new Runnable()
{
#Override
public void run()
{
while(true)
{
for (String c: colorsList)
{
int color = Color.parseColor(c);
Log.d(TAG, color+"");
view.setBackgroundColor(color);
SystemClock.sleep(500);
}
}
}
});
Log.d(TAG, "returned null");
return null;
}
}
private void getData() {
final String serverURL;
final JsonArrayRequest request;
final RequestQueue queue;
serverURL = "https://api.mlab.com/api/1/databases/comp3717final/collections/colours?apiKey=qR2ag5UaRrHBxDm6KEyg95EESmfY5Bcf";
queue = Volley.newRequestQueue(this);
request = new JsonArrayRequest(serverURL,
new onJSONResponse(),
new onJSONError());
queue.add(request);
}
private class onJSONResponse implements Response.Listener<JSONArray>
{
#Override
public void onResponse(JSONArray response)
{
final int length;
int i;
i = 0;
length = response.length();
try {
for (; i < length; i++) {
final JSONObject colorObject;
final JSONObject hexObject;
final String colorName;
final String hexCode;
colorObject = response.getJSONObject(i);
colorName = colorObject.getString("color");
hexCode = colorObject.getString("value");
Log.d(TAG, colorName + " => " + hexCode);
colorsList.add(colorName);
}
} catch (final JSONException ex) {
Log.d(TAG, "Error getting json object: " + i, ex);
colorsList.clear();
}
Log.d(TAG, "working");
}
}
private static class onJSONError implements Response.ErrorListener
{
#Override
public void onErrorResponse(VolleyError error)
{
Log.d(TAG, "JSON ERROR");
}
}
}
The layout:
<?xml version="1.0" encoding="utf-8"?>
<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"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.peymantp.androidfinal.CycleActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Done"
android:id="#+id/button6"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginBottom="32dp" />
</RelativeLayout>
getData which has network calls and AsyncTask execution happening simultaneously, which may cause colorList initialization after asyncTask is done. You need to call getData in synchronized way before AsysncTask access colorList.
Related
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, but after the data is update, databinding not update my textview. here my Detail Activity Class :
public class DetailActivity extends BaseActivity<ActivityDetailBinding, DetailViewModel> implements DetailNavigator {
#Inject
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() {
return detailViewModel;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
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 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);
}, 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 {
originalName.set(detailResponse.getOriginal_title());
}
originalName.notifyChange();
if (detailResponse.getFirst_air_date() != null) {
releaseDate.set(detailResponse.getFirst_air_date());
} else {
releaseDate.set(detailResponse.getRelease_date());
}
overview.set(String.valueOf(detailResponse.getOverview()));
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);
}
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>
<variable
name="viewModel"
type="test.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"
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"
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"
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"
tools:text="#string/hint_genres" />
<TextView
android:id="#+id/text_duration"
style="#style/FontText.Normal.White"
android:layout_marginTop="#dimen/margin10dp"
android:layout_marginEnd="#dimen/margin15dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/text_release"
tools:text="#string/hint_duration" />
<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.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/text_duration" />
<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_duration"
tools:text="#string/hit_rating" />
<TextView
android:id="#+id/text_default_rating"
style="#style/FontText.Rating"
android:textStyle="normal"
app:layout_constraintRight_toLeftOf="parent"
app:layout_constraintStart_toEndOf="#+id/text_rating"
app:layout_constraintTop_toBottomOf="#+id/text_duration"
tools: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"
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 try to show one data first, that is OriginalName for text_title, went I debug my application
public ObservableField<String> getOriginalName() {
return originalName;
}
getOriginalName in class ViewModel, just called before I retrieve my response, but after OriginalName is set, the UI not update and getOriginalName is never called again.I already add originalName.notifyChange(); after the data is set, but it doesn't seem change anything.
I already frustased.. so please... I hope anybody can help me to show me what to do. Thank you very much.
Remove this below line from Detail Activity
setContentView(R.layout.activity_detail);
In your base activity you have performDataBinding method which set the layout id using DataBindingUtil class.
mViewDataBinding = DataBindingUtil.setContentView(this, getLayoutId());
this.mViewModel = mViewModel == null ? getViewModel() : mViewModel;
mViewDataBinding.setVariable(getBindingVariable(), mViewModel);
mViewDataBinding.setLifecycleOwner(this);
mViewDataBinding.executePendingBindings();
I am trying to make a news app, data obtained from RSS feed. I get xml response from the feed. And I am using XmlPullParser to parse the xml. The parsing is a success. I can see the values in my log.
But somehow I am not able to fill them in my recyclerView. It's all just blank. My java class is:
public class RssNewsActivity extends AppCompatActivity {
private static final String TAG = RssNewsActivity.class.toString();
RssFeedAdapter adapter;
RecyclerView recyclerView_rssFeed;
SwipeRefreshLayout swipeRefreshLayout;
private List<RssModel> listResponseModel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rss_news);
initialize();
recyclerView_rssFeed.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
recyclerView_rssFeed.setLayoutManager(linearLayoutManager);
adapter = new RssFeedAdapter(RssNewsActivity.this, listResponseModel);
recyclerView_rssFeed.setAdapter(adapter);
fetchNewsFeed();
//if user swipes the recycler then refresh content page
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
fetchNewsFeed();
}
});
}
private void initialize() {
swipeRefreshLayout = findViewById(R.id.swipeRefresh_rssFeed);
recyclerView_rssFeed = findViewById(R.id.recyclerView_rssFeed);
listResponseModel = new ArrayList<>();
}
private void fetchNewsFeed() {
String url = "here is my news feed url";
StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
listResponseModel.clear();
try {
listResponseModel = parseNewsFeed(response);
} catch (XmlPullParserException | IOException e) {
Log.e(TAG, e.getMessage());
}
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
RequestQueue queue = Volley.newRequestQueue(this);
queue.add(request);
}
private List<RssModel> parseNewsFeed(String response) throws XmlPullParserException,
IOException {
XmlPullParserFactory parserFactory = XmlPullParserFactory.newInstance();
parserFactory.setNamespaceAware(true);
XmlPullParser xmlPullParser = parserFactory.newPullParser();
xmlPullParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
xmlPullParser.setInput(new StringReader(response));
return processParsing(xmlPullParser);
}
private List<RssModel> processParsing(XmlPullParser xmlPullParser) throws IOException, XmlPullParserException {
List<RssModel> listRssFeed = new ArrayList<>();
int eventType = xmlPullParser.getEventType();
RssModel rssModel = null;
xmlPullParser.nextTag();
while (eventType != XmlPullParser.END_DOCUMENT) {
String eltName;
switch (eventType) {
case XmlPullParser.START_DOCUMENT:
break;
case XmlPullParser.START_TAG:
eltName = xmlPullParser.getName();
if ("item".equals(eltName)) {
rssModel = new RssModel();
} else if (rssModel != null) {
if ("title".equals(eltName)) {
String title = xmlPullParser.nextText();
rssModel.setTitle(title);
Log.d(TAG, "title: " + title);
} else if ("link".equals(eltName)) {
String link = xmlPullParser.nextText();
rssModel.setLink(link);
Log.d(TAG, "link: " + link);
}
}
break;
case XmlPullParser.END_TAG:
eltName = xmlPullParser.getName();
if ("item".equals(eltName) && rssModel != null) {
listRssFeed.add(rssModel);
}
break;
}
eventType = xmlPullParser.next();
}
return listRssFeed;
}
}
my xml design is:
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context="rssnewsfeed.RssNewsActivity">
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipeRefresh_rssFeed"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView_rssFeed"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
This is my adapter class
public class RssFeedAdapter extends RecyclerView.Adapter<RssFeedAdapter.RssViewHolder> {
private Context mContext;
private List<RssModel> mRssFeeds;
public RssFeedAdapter(Context mContext, List<RssModel> mRssFeeds) {
this.mContext = mContext;
this.mRssFeeds = mRssFeeds;
}
#NonNull
#Override
public RssViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(mContext).inflate(R.layout.rss_feed_layout, viewGroup, false);
return new RssViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull RssViewHolder rssViewHolder, int i) {
RssModel post = mRssFeeds.get(i);
rssViewHolder.textView_title.setText(post.getTitle());
rssViewHolder.textView_link.setText(post.getLink());
}
#Override
public int getItemCount() {
return mRssFeeds.size();
}
public class RssViewHolder extends RecyclerView.ViewHolder {
private TextView textView_title, textView_link;
public RssViewHolder(#NonNull View itemView) {
super(itemView);
textView_title = itemView.findViewById(R.id.textView_title);
textView_link = itemView.findViewById(R.id.textView_link);
}
}
}
And finally this is my model class:
public class RssModel {
private String title;
private String link;
public RssModel() {
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
}
I tried many ways but no success. I don't know what I am missing. I will be grateful for any guidance. Thanks.
Giving " = " will create a new instance of ArrayList apart from which is already binded to RecyclerView adapter.
So, you need to change this,
listResponseModel = parseNewsFeed(response);
to
listResponseModel.addAll(parseNewsFeed(response));
This happens because the Rss list which you're passing to recycler view adapter is null as you mentioned earlier you're successfully getting the values in log so another guaranteed workaround is to set the values into an separate arraylist.
So inside your class simply create arraylist:
private ArrayList<String> title;
private ArrayList<String> post;
This will be your initialize method:
private void initialize()
{
swipeRefreshLayout = findViewById(R.id.swipeRefresh_rssFeed);
recyclerView_rssFeed = findViewById(R.id.recyclerView_rssFeed);
title = new ArrayList<>();
post = new ArrayList<>();
}
Now simply pass your values to arraylist:
title.add(title)
post.add(post)
Now pass those arraylist to adapter:
adapter = new RssFeedAdapter(RssNewsActivity.this, title,post);
recyclerView_rssFeed.setAdapter(adapter);
After this initialize arraylist in adapter and fetch your values!
One more Important thing inside your oncreate() place your fetchNewsFeed(); method before initializing the adapter
initialize();
fetchNewsFeed();
recyclerView_rssFeed.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
recyclerView_rssFeed.setLayoutManager(linearLayoutManager);
adapter = new RssFeedAdapter(RssNewsActivity.this, listResponseModel);
recyclerView_rssFeed.setAdapter(adapter);
I am having a problem with cardview not displaying some from the database.
My app connects to a grails back end which has a PostgreSQL db.
I have a cardview inside a recyclerview. It receives 7 values in form of JSON but on running the app, only 5 are displayed. I try doing System.out of the JSON in the stack trace and I find that all the 7 values are received so everything is okay on that front.
For clarity purposes, the fields that are not being displayed are labs("labs") and drugs administered("drugsAdministered").
Here is the main class(ClinicalHistory.java), the adapter class, the xml and the stack-trace.
ClinicalHistory.java
public class ClinicalHistory extends AppCompatActivity {
RecyclerView clinicalHistory_rv;
SwipeRefreshLayout swipeRefreshLayout;
List<com.example.user.eafya.models.ClinicalHistory> clinicalHistory_List;
com.example.user.eafya.models.ClinicalHistory clinicalHistory;
ClinicalHistoryAdapter clinicalHistoryAdapter;
private StringRequest clinicalHistoryRequest;
private LinearLayout no_data;
private LinearLayoutManager linearLayoutManager;
private RequestQueue requestQueue;
private ProgressDialog pb;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_clinical_history);
initWidgets();
fetchData();
}
private void fetchData() {
pb = new ProgressDialog(this);
pb.setIcon(R.mipmap.ic_launcher);
pb.setTitle("Please wait");
pb.setCancelable(false);
pb.setMessage("Loading data..");
pb.show();
clinicalHistoryRequest = new StringRequest(Request.Method.GET, Configs.URL_LOGIN + Configs.CLINICALHISTORY_PATH, new Response.Listener<String>() {
#Override
public void onResponse(String result) {
pb.dismiss();
System.out.print("======================================"+ result);
try {
JSONObject jsonObject = new JSONObject(result);
JSONArray jsonArray = jsonObject.getJSONArray("mVisit");
for (int i=0;i<jsonArray.length();i++){
System.out.print("----------------"+jsonArray.getJSONObject(i).getString("labs"));
}
Log.d("myError: ", String.valueOf(jsonArray.length()));
if(jsonArray.length()<1) {
clinicalHistory_List.clear();
no_data.setVisibility(View.VISIBLE);
}else if( jsonArray.length()>0){
if(no_data.getVisibility()==View.VISIBLE){
no_data.setVisibility(View.GONE);
}
for(int i=0 ; i<jsonArray.length() ; i++){
JSONObject data = jsonArray.getJSONObject(i);
clinicalHistory = new com.example.user.eafya.models.ClinicalHistory();
clinicalHistory.setDate(data.getString("dateCreated"));
clinicalHistory.setHospital(data.getString("hospitalAttended"));
clinicalHistory.setDoctor(data.getString("attendingDoctor"));
clinicalHistory.setLabs(data.getString("labs"));
clinicalHistory.setChiefComplains(data.getString("chiefComplains"));
clinicalHistory.setDrugs(data.getString("drugsAdministered"));
clinicalHistory_List.add(clinicalHistory);
}
clinicalHistoryAdapter = new ClinicalHistoryAdapter(ClinicalHistory.this, clinicalHistory_List);
linearLayoutManager = new LinearLayoutManager(ClinicalHistory.this);
clinicalHistory_rv.setLayoutManager(linearLayoutManager);
clinicalHistory_rv.setItemAnimator(new DefaultItemAnimator());
clinicalHistory_rv.setAdapter(clinicalHistoryAdapter);
clinicalHistory_rv.setSaveEnabled(true);
clinicalHistory_rv.setSaveFromParentEnabled(true);
clinicalHistoryAdapter.notifyDataSetChanged();
}
} catch (JSONException e) {
Log.d("MaeraJ",e.toString());
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
pb.dismiss();
AlertDialog.Builder dialog = new AlertDialog.Builder(ClinicalHistory.this);
dialog.setTitle("Something went wrong !!");
dialog.setCancelable(true);
dialog.setIcon(R.mipmap.ic_launcher);
dialog.setMessage("Check your data connection");
dialog.setPositiveButton("RETRY", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
//retry
dialogInterface.dismiss();
fetchData();
}
});
dialog.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
//cancel
dialogInterface.dismiss();
}
});
dialog.create();
dialog.show();
Log.d("Maera",volleyError.toString());
}
});
requestQueue.add(clinicalHistoryRequest);
}
private void initWidgets() {
requestQueue = Volley.newRequestQueue(this);
no_data = findViewById(R.id.nodata_LY);
clinicalHistory_rv = findViewById(R.id.clinicalHistory_RV);
clinicalHistory_List = new ArrayList<>();
swipeRefreshLayout = findViewById(R.id.swipeContainer);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
refresh();
}
});
}
private void refresh() {
try {
clinicalHistory_List.clear();
fetchData();
swipeRefreshLayout.setRefreshing(false);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
case R.id.home:
onBackPressed();
break;
}
return super.onOptionsItemSelected(item);
}
}
Adapter class(ClinicalHistoryAdapter.java)
public class ClinicalHistoryAdapter extends RecyclerView.Adapter<ClinicalHistoryAdapter.myViewHolder> {
Context ctx;
List<ClinicalHistory> clinicalHistoryList;
ClinicalHistory clinicalHistoryModel;
LayoutInflater inflater;
public ClinicalHistoryAdapter(Context ctx, List<ClinicalHistory> clinicalHistoryList) {
this.ctx = ctx;
this.clinicalHistoryList = clinicalHistoryList;
inflater = LayoutInflater.from(ctx);
}
public class myViewHolder extends RecyclerView.ViewHolder {
TextView clinicalHist_date_TV,clinicalHist_hospital, clinicalHist_doctor,clinicalHist_chiefComplains, clinicalHist_labs, clinicalHist_drugs;
ImageView clinicalHist_img;
public myViewHolder(View itemView) {
super(itemView);
clinicalHist_img = itemView.findViewById(R.id.clinicalHist_image_IV);
clinicalHist_date_TV = itemView.findViewById(R.id.clinicalHist_date__TV);
clinicalHist_hospital = itemView.findViewById(R.id.clinicalHist_hospital_TV);
clinicalHist_doctor = itemView.findViewById(R.id.clinicalHist_doctor);
clinicalHist_chiefComplains = itemView.findViewById(R.id.clinicalHist_chief_complains_TV);
clinicalHist_labs = itemView.findViewById(R.id.clinicalHist_labs_TV);
clinicalHist_drugs = itemView.findViewById(R.id.clinicalHist_drugs_TV);
}
}
#Override
public ClinicalHistoryAdapter.myViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View my_view = inflater.inflate(R.layout.clinical_history_item,viewGroup,false);
return new myViewHolder(my_view);
}
#Override
public void onBindViewHolder(ClinicalHistoryAdapter.myViewHolder myViewHolder, final int position) {
clinicalHistoryModel = new ClinicalHistory();
clinicalHistoryModel = clinicalHistoryList.get(position);
myViewHolder.clinicalHist_date_TV.setText(clinicalHistoryModel.getDate());
myViewHolder.clinicalHist_hospital.setText(clinicalHistoryModel.getHospital());
myViewHolder.clinicalHist_doctor.setText(clinicalHistoryModel.getDoctor());
myViewHolder.clinicalHist_chiefComplains.setText(clinicalHistoryModel.getChiefComplains());
myViewHolder.clinicalHist_labs.setText(clinicalHistoryModel.getLabs());
myViewHolder.clinicalHist_drugs.setText(clinicalHistoryModel.getDrugs());
myViewHolder.clinicalHist_doctor.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
goToDetails(position);
}
});
myViewHolder.clinicalHist_hospital.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
goToDetails(position);
}
});
Glide.with(ctx).load(clinicalHistoryModel.getImg()).placeholder(R.drawable.loader).error(R.drawable.header).into(myViewHolder.clinicalHist_img);
}
private void goToDetails(int pos) {
clinicalHistoryModel = clinicalHistoryList.get(pos);
Intent intent = new Intent(ctx,MedicalDetailActivity.class);
intent.putExtra("dateCreated", clinicalHistoryModel.getDate());
intent.putExtra("clinicalHist_img", clinicalHistoryModel.getImg());
intent.putExtra("hospitalAttended", clinicalHistoryModel.getHospital());
intent.putExtra("attendingDoctor", clinicalHistoryModel.getDoctor());
intent.putExtra("chiefComplaints", clinicalHistoryModel.getChiefComplains());
intent.putExtra("labs", clinicalHistoryModel.getLabs());
intent.putExtra("drugs", clinicalHistoryModel.getLabs());
ctx.startActivity(intent);
}
#Override
public int getItemCount() {
return clinicalHistoryList.size();
}
}
The xml file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="4dp">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_margin="2dp"
android:orientation="horizontal"
android:padding="2dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/clinicalHist_image_IV"
android:layout_width="110dp"
android:layout_height="80dp"
android:layout_gravity="top"
android:scaleType="fitXY"
android:src="#drawable/header" />
<LinearLayout
android:padding="4dp"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:textAlignment="textStart"
android:layout_gravity="start"
android:id="#+id/clinicalHist_date__TV"
android:text="21/09/2012"
android:textColor="#color/colorAccent"
android:textAppearance="#android:style/TextAppearance.DeviceDefault.Medium"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:textAlignment="textStart"
android:layout_gravity="start"
android:id="#+id/clinicalHist_hospital_TV"
android:text="Hema Hospital"
android:textColor="#color/colorAccent"
android:textAppearance="#android:style/TextAppearance.DeviceDefault.Medium"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:id="#+id/clinicalHist_doctor"
android:text="Dr.Lilian"/>
<TextView
android:layout_gravity="center"
android:id="#+id/clinicalHist_labs_TV"
android:text=" Brucella "
android:textColor="#000"
android:textAppearance="#android:style/TextAppearance.DeviceDefault.Medium"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:layout_gravity="center"
android:id="#+id/clinicalHist_chief_complains_TV"
android:text=" Headache "
android:textColor="#000"
android:textAppearance="#android:style/TextAppearance.DeviceDefault.Medium"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:layout_gravity="center"
android:id="#+id/clinicalHist_drugs_TV"
android:text=" Brufen "
android:textColor="#000"
android:textAppearance="#android:style/TextAppearance.DeviceDefault.Medium"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
The stack trace
I/System.out: ======================================{"mVisit":[{"id":1,"chiefComplains":"Headache","dateCreated":"2017-08-11T21:00:00Z","labs":"Brucella","hospitalAttended":"Hema Hospital","drugsAdministered":"Tramadol","attendingDoctor":"Dr. Kisinga"
I have found the solution. The problem was in the model.
This was my previous model. Note the parameters in the
setDrugs() and setLabs().
public class ClinicalHistory {
String img;
String date;
String labs;
String hospital;
String chiefComplains;
String doctor;
String drugs;
public ClinicalHistory() {
}
public String getImg() {
return img;
}
public void setImg(String img) {
this.img = img;
}
public String getHospital() {
return this.hospital = hospital ;
}
public void setHospital(String hospital) {
this.hospital = hospital;
}
public String getChiefComplains(){return this.chiefComplains = chiefComplains;}
public void setChiefComplains(String chiefComplains){ this.chiefComplains = chiefComplains;}
public String getLabs() {
return this.labs = labs ;
}
public void setLabs(String hospital) {
this.labs = labs;
}
public String getDoctor() {
return this.doctor = doctor ;
}
public void setDoctor(String doctor) {
this.doctor = doctor;
}
public void setDrugs(String hospital) {
this.drugs = drugs;
}
public String getDrugs() {
return this.drugs = drugs ;
}
public void setDate(String date) {
this.date = date;
}
public String getDate() {
return date;
}
}
After I made this change it worked
public class ClinicalHistory {
String img;
String date;
String labs;
String hospital;
String chiefComplains;
String doctor;
String drugs;
public ClinicalHistory() {
}
public String getImg() {
return img;
}
public void setImg(String img) {
this.img = img;
}
public String getHospital() {
return this.hospital = hospital ;
}
public void setHospital(String hospital) {
this.hospital = hospital;
}
public String getChiefComplains(){return this.chiefComplains = chiefComplains;}
public void setChiefComplains(String chiefComplains){ this.chiefComplains = chiefComplains;}
public String getLabs() {
return this.labs = labs ;
}
public void setLabs(String labs) {
this.labs = labs;
}
public String getDoctor() {
return this.doctor = doctor ;
}
public void setDoctor(String doctor) {
this.doctor = doctor;
}
public void setDrugs(String drugs) {
this.drugs = drugs;
}
public String getDrugs() {
return this.drugs = drugs ;
}
public void setDate(String date) {
this.date = date;
}
public String getDate() {
return date;
}
}
I'm working on a small project where a user is shown his result after he tries to login and he already taken the quiz on my app.
So i'm using a page like this to display result.
But i cannot display my score. This page also has an option to share your score which is working fine and displaying score.Share option containing result.
I'm attaching my XML and Java Code kindly please help me solve the issue that'll be great help.
Thanks & Regards
BugAdder
XML Code:
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center|top">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:padding="20dp"
android:textAlignment="center"
android:textSize="25sp"
android:textStyle="bold"
android:text="#string/login_score_title"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:padding="20dp"
android:textSize="25sp"
android:textStyle="bold"
android:text="#string/score_result"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:textStyle="bold"
android:id="#+id/login_score_text"/>
<Button
android:padding="20dp"
android:layout_marginTop="75dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/login_share_button"
android:text="#string/share_button"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="#string/exit_button"
android:drawableEnd="#drawable/arrow_right"
android:drawableRight="#drawable/arrow_right"
android:id="#+id/login_exit_button"/>
</LinearLayout>
</ScrollView>
Java Code:
public class QuizLoginScore extends AppCompatActivity {
private List<ScoreItem> mScoreItems = new ArrayList<>();
private ProgressDialog mProgressDialog;
private String mScore;
private TextView mScoreTextView;
private Button mShareButton;
private Button mExitButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.score_login_quiz);
mScoreTextView = (TextView)findViewById(R.id.login_score_text);
mShareButton = (Button)findViewById(R.id.login_share_button);
mExitButton = (Button)findViewById(R.id.login_exit_button);
new FetchScoresTask().execute();
mScoreTextView.setText(mScore);
mExitButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(Build.VERSION.SDK_INT >= 21){
finishAndRemoveTask();
}else{
finishAffinity();
System.exit(0);
}
}
});
mShareButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("text/plain");
i.putExtra(Intent.EXTRA_TEXT,getScoreShareReport(mScore));
i.putExtra(Intent.EXTRA_SUBJECT,getString(R.string.score_report_subject));
i = Intent.createChooser(i,getString(R.string.send_report));
startActivity(i);
}
});
}
public String getScoreShareReport(String score){
String result;
StringBuilder sb = new StringBuilder();
sb.append("QuizApp!").
append("\n\n").
append("I Just Scored").
append(" \' ").
append(score).
append(" \' ").
append("marks out of \' 100 \' in Latest Quiz on QuizApp!\nWhats your Score Huh?");
result = sb.toString();
return result;
}
private class FetchScoresTask extends AsyncTask<Void, Void, List<ScoreItem>> {
#Override
protected void onPreExecute() {
mProgressDialog = new ProgressDialog(QuizLoginScore.this);
mProgressDialog.setTitle("Downloading Score");
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.setMessage("Please wait while the score is being downloaded!");
mProgressDialog.setCancelable(false);
mProgressDialog.show();
}
#Override
protected List<ScoreItem> doInBackground(Void... params) {
return new ScoreFetcher().fetchScoreItems();
}
#Override
protected void onPostExecute(List<ScoreItem> scoreItems) {
mScoreItems = scoreItems;
for(int i = 0; i < mScoreItems.size(); i++){
if(mScoreItems.get(i).getUserId().equals(QuizLogin.mUserIdString)){
mScore = String.valueOf(mScoreItems.get(i).getScore());
break;
}
}
mProgressDialog.dismiss();
}
}
}
mScore is set in a async task. so you must set text in onPostExecute. try following code:
public class QuizLoginScore extends AppCompatActivity {
private List<ScoreItem> mScoreItems = new ArrayList<>();
private ProgressDialog mProgressDialog;
private String mScore;
private TextView mScoreTextView;
private Button mShareButton;
private Button mExitButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.score_login_quiz);
mScoreTextView = (TextView)findViewById(R.id.login_score_text);
mShareButton = (Button)findViewById(R.id.login_share_button);
mExitButton = (Button)findViewById(R.id.login_exit_button);
new FetchScoresTask().execute();
mScoreTextView.setText(mScore);
mExitButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(Build.VERSION.SDK_INT >= 21){
finishAndRemoveTask();
}else{
finishAffinity();
System.exit(0);
}
}
});
mShareButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("text/plain");
i.putExtra(Intent.EXTRA_TEXT,getScoreShareReport(mScore));
i.putExtra(Intent.EXTRA_SUBJECT,getString(R.string.score_report_subject));
i = Intent.createChooser(i,getString(R.string.send_report));
startActivity(i);
}
});
}
public String getScoreShareReport(String score){
String result;
StringBuilder sb = new StringBuilder();
sb.append("QuizApp!").
append("\n\n").
append("I Just Scored").
append(" \' ").
append(score).
append(" \' ").
append("marks out of \' 100 \' in Latest Quiz on QuizApp!\nWhats your Score Huh?");
result = sb.toString();
return result;
}
private class FetchScoresTask extends AsyncTask<Void, Void, List<ScoreItem>> {
#Override
protected void onPreExecute() {
mProgressDialog = new ProgressDialog(QuizLoginScore.this);
mProgressDialog.setTitle("Downloading Score");
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.setMessage("Please wait while the score is being downloaded!");
mProgressDialog.setCancelable(false);
mProgressDialog.show();
}
#Override
protected List<ScoreItem> doInBackground(Void... params) {
return new ScoreFetcher().fetchScoreItems();
}
#Override
protected void onPostExecute(List<ScoreItem> scoreItems) {
mScoreItems = scoreItems;
for(int i = 0; i < mScoreItems.size(); i++){
if(mScoreItems.get(i).getUserId().equals(QuizLogin.mUserIdString)){
mScore = String.valueOf(mScoreItems.get(i).getScore());
mScoreTextView.setText(mScore);
break;
}
}
mProgressDialog.dismiss();
}
}
}
Put your mScore string in log to see if you are getting the data in logcat. Also try changing the color of your textview. Also put your textview.settext() in onpostexecute(); method
Set text from onPostExecute():
#Override
protected void onPostExecute(List<ScoreItem> scoreItems) {
mScoreItems = scoreItems;
for(int i = 0; i < mScoreItems.size(); i++){
if(mScoreItems.get(i).getUserId().equals(QuizLogin.mUserIdString)){
mScore = String.valueOf(mScoreItems.get(i).getScore());
mScoreTextView.setText(mScore);
break;
}
}
mProgressDialog.dismiss();
}
I have set up a button with an onClick method called ButtonRoll which randomly generates a number from 1-100 then display the output below the button in a text view. This works fine but what I would like to move onto is to be able to cycle through 20 numbers being generated. I have tried the following the but it will only display the last number being generated. I am guessing this is because the UI isn't being updated untill the last number is generated.
public void ButtonRoll(View view) {
int n;
Random rand = new Random();
TextView textRoll = (TextView) findViewById(R.id.textview_roll);
for (int i=0; i<20; i++){
try {
Thread.sleep(200);
n = rand.nextInt(100) + 1;
String roll = String.valueOf(n);
textRoll.setText("Random number is " + roll);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Would I have to use a Handler at all? Or is there a simpler solution?
Thanks for your time.
Give this a try.
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<Button android:id="#+id/button_roll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:text="Roll"/>
<TextView android:id="#+id/textview_roll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/button_roll" />
</RelativeLayout>
MainActivity.java
public class MainActivity extends Activity implements OnClickListener
{
private class Roller implements Runnable
{
private int numTimes;
private long delayMillis;
public Roller(int numTimes, long delayMillis)
{
this.numTimes = numTimes;
this.delayMillis = delayMillis;
}
#Override
public void run()
{
if (textRoll != null)
{
int n = rand.nextInt(100) + 1;
String roll = String.valueOf(n);
textRoll.setText("Random number is " + roll);
numTimes--;
if (numTimes > 0)
{
textRoll.postDelayed(this, delayMillis);
}
}
}
}
private TextView textRoll;
private Random rand = new Random();
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button_roll).setOnClickListener(this);
textRoll = (TextView)findViewById(R.id.textview_roll);
}
#Override
public void onDestroy()
{
findViewById(R.id.button_roll).setOnClickListener(null);
textRoll = null;
super.onDestroy();
}
#Override
public void onClick(View v)
{
int id = v.getId();
if (id == R.id.button_roll)
{
findViewById(R.id.textview_roll).post(new Roller(20, 100));
}
}
}
you can use handler concept:
There are several ways to update your UI and modify a View such as a TextView from outside of the UI Thread. A Handler is just one method.
Here is an example that allows a single Handler respond to various types of requests.
private final static int DO_UPDATE_TEXT = 0;
private final static int DO_THAT = 1;
private final Handler myHandler = new Handler() {
public void handleMessage(Message msg) {
final int what = msg.what;
switch(what) {
case DO_UPDATE_TEXT: doUpdate(); break;
case DO_THAT: doThat(); break;
}
}
};
Update the UI in one of your functions, which is now on the UI Thread:
private void doUpdate() {
myTextView.setText("updating..");
}
in your asynchronous task, send a message to the Handler. There are several ways to do it. This may be the simplest:
myHandler.sendEmptyMessage(DO_UPDATE_TEXT);
After noticing the .post method as mentioned beforehand, I had a play and came up with this version which does the same. Can you see any reason why is would unadvisable to run it this way?
public void ButtonRoll(View view) {
new Thread(new Runnable() {
#Override
public void run() {
for(int i = 0; i<50;i++) {
try {
Thread.sleep(50);
final TextView textRoll = (TextView) findViewById(R.id.textview_roll);
int n;
Random rand = new Random();
n = rand.nextInt(100) + 1;
final String roll = String.valueOf(n);
textRoll.post(new Runnable() {
#Override
public void run() {
textRoll.setText("Random number is " + roll);
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}