How to resolve ClassCastException: java.lang.String cannot be cast exception - java

I need help. I have two methods of shared preference. They are getList and setList.
This is setList()
public static void setList(Application activity, List<tcmb> mValuesList) {
StringBuilder valuesBuilder = new StringBuilder();
/*Log.d(TAG, "List Size ------ \t: " + mValuesList.size());*/
for (tcmb s : mValuesList) {
valuesBuilder.append(s);
valuesBuilder.append(",");
Log.d(TAG, "setValuestcmb: " + valuesBuilder.toString());
}
SharedPreferences values = activity.getSharedPreferences("dd", MODE_PRIVATE);
SharedPreferences.Editor editor = values.edit();
editor.putString("ss", valuesBuilder.toString());
editor.apply();
}
This is getList()
public static List<tcmb> getList(Activity a) {
SharedPreferences values = a.getSharedPreferences("dd", MODE_PRIVATE);
String wordsString = values.getString("ss", "");
/* Log.d(TAG, "wordsString \t:" + wordsString);*/
String[] itemWords = wordsString.split(",");
List<String> itemList = new ArrayList<String>();
itemList.addAll(Arrays.asList(itemWords));
dovizList = (List)itemsList;
Log.d(TAG, "getValuestcmb: " + dovizList.size());
return dovizList;
}
For the values I got, I run the setList method in the asyncTask class of Main Activity that assigns to shared preference.
Then for I get to values, I run the getList method in the asyncTask class of Fragment.
And I get the object values.namely, I can see the values I get from the logcat.
[com.example.lscodex.ddddd.Model.tcmb#4ff695, com.example.lscodex.ddddd.Model.tcmb#b6b93aa, com.example.lscodex.ddddd.Model.tcmb#347db9b, com.example.lscodex.ddddd.Model.tcmb#f63eb38, com.example.lscodex.ddddd.Model.tcmb#4866711, com.example.lscodex.ddddd.Model.tcmb#8c74076, com.example.lscodex.ddddd.Model.tcmb#3be9677, com.example.lscodex.ddddd.Model.tcmb#10882e4, com.example.lscodex.ddddd.Model.tcmb#8d9634d, com.example.lscodex.ddddd.Model.tcmb#b5eee02, com.example.lscodex.ddddd.Model.tcmb#b7c2313, com.example.lscodex.ddddd.Model.tcmb#a3ce950, com.example.lscodex.ddddd.Model.tcmb#ee5e749, com.example.lscodex.ddddd.Model.tcmb#fd1e84e, com.example.lscodex.ddddd.Model.tcmb#b7bdd6f, com.example.lscodex.ddddd.Model.tcmb#40f4a7c, com.example.lscodex.ddddd.Model.tcmb#b1caf05, com.example.lscodex.ddddd.Model.tcmb#b683b5a, com.example.lscodex.ddddd.Model.tcmb#f12e18b]
totally 19 values.
But when I cast values to recylerView's bindHolder in the fragment class, I get an error is that
java.lang.ClassCastException: java.lang.String cannot be cast to com.example.lscodex.ddddd.Model.tcmb
This is asyncTask from fragment
private class DownloadXmlTask extends AsyncTask<Void, Integer, List<tcmb>> {
#Override
protected void onPreExecute() {
super.onPreExecute();
mProgressBar.setVisibility(View.VISIBLE);
}
#Override
protected List<tcmb> doInBackground(Void... voids) {
return SharedPreferenceValues.getList(getActivity());
}
#Override
protected void onPostExecute(List<tcmb> tcmb) {
if (tcmb.size() == 0) {
mtcmbList = tcmb;
setupAdapter();
mRecyclerViewAnim.runLayoutAnimation(getContext(), mRecyclerView);
mProgressBar.setVisibility(View.INVISIBLE);
} else if (mRecyclerView != null) {
mtcmbList.addAll(tcmb);
Log.d(TAG, "onPostExecute: " + mtcmbList.size());
mRecyclerView.getAdapter().notifyDataSetChanged();
dateUpdate();
mRecyclerViewAnim.runLayoutAnimation(getContext(), mRecyclerView);
mProgressBar.setVisibility(View.INVISIBLE);
mSwipeRefreshLayout.setRefreshing(false);
}
}
}
and the place where I got the error.
#Override
public void onBindViewHolder(tcmbHolder holder, int position) {
tcmb tcmb= mtcmbList.get(position); ---- the error here
holder.bindTcmb(tcmb);
I don't know why?
EDIT
I try it with the shared preferences, I get XML list data from splash screen and import it into other activity.
private class splashTask extends AsyncTask<Void, Integer, List<tcmb>> {
private Activity mContext;
public splashTask(Activity c){
this.mContext = c;
}
#Override
protected void onPreExecute() {
mSplashProgressBar.setProgress(0);
}
#Override
protected List<tcmbDoviz> doInBackground(Void... voids) {
List<tcmb> tcmbList = new ConnectionXmlParser().getXmlFile(getApplicationContext());
try {
int getvalues = ConnectionXmlParser.howLong();
Log.d(TAG, "doInBackground: " +getvalues);
for (int i=0;i<getvalues;i++){
Log.d(TAG, "doInBackground: " +i);
publishProgress(((int)i*100)/getvalues);
Log.d(TAG, "Publishing " + ((int)i*100/getvalues));
}
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
return tcmbList;
}
#Override
protected void onPostExecute(List<tcmbDoviz> list) {
mtcmbList.addAll(list);
SharedPreferenceValues.setValuesList(getApplication(),mtcmbList);
splashScreen();
mSplashProgressBar.setVisibility(View.GONE);
}
#Override
protected void onProgressUpdate(Integer... values) {
mSplashProgressBar.setProgress(values[0]);
super.onProgressUpdate(values);
}

You are trying to change List<String> to List<tcmb> and problem lies here
public static List<tcmb> getList(Activity a){
// your code
//
List<String> itemList = new ArrayList<String>();
itemList.addAll(Arrays.asList(itemWords));
dovizList = (List)itemsList;
Log.d(TAG, "getValuestcmb: " + dovizList.size());
return dovizList;
Also, I don't understand, what exactly you are trying to achieve here.
List<String> itemsList = new ArrayList<String>();
dovizList = (List)itemsList;
But, as per code shared, you need to change
List<String> itemsList = new ArrayList<String>();
to
List<tcmb> itemsList = new ArrayList<tcmb>();
And, you don't need
dovizList = (List)itemsList;

I found how to do it.
to save XML List object with Shared Preferences in splashscreen.activity
public static void setValues(Context context, List<tcmb> curProduct){
Gson gson = new Gson();
String jsonCurProduct = gson.toJson(curProduct);
SharedPreferences sharedPref = context.getSharedPreferences("Prefs", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("dd", jsonCurProduct);
editor.apply();
Log.d(TAG, "setValues: " + jsonCurProduct);
}
then, to get the List object with Shared Preferences in the fragment
public static List<tcmb> getValuesAltın(Context context){
Gson gson = new Gson();
List<tcmbDoviz> productFromShared = new ArrayList<>();
SharedPreferences sharedPref = context.getSharedPreferences("Prefs", Context.MODE_PRIVATE);
String jsonPreferences = sharedPref.getString("dd", "");
Type type = new TypeToken<List<tcmb>>() {}.getType();
productFromShared = gson.fromJson(jsonPreferences, type);
return productFromShared;
}
finally, Thanks, Ravi.

Related

How to properly pass context to AsyncTask and then to another class?

I'm working on app that will use biometric as an option to login. Before I use the actual biometric prompt I need to check one thing from server - I use AsyncTask to do it. So, to sum up - I invoke AsyncTask from Parent Activity (login.java), and then AsyncTask uses biometricUtils.java class, that makes biometric prompt. The point is, I keep passing null instead of context to biometricUtils.java:
Attempt to invoke virtual method 'java.util.concurrent.Executor android.content.Context.getMainExecutor()' on a null object reference at biometricUtils.<init>(biometricUtils.java:34)
I have no idea to pass the context correctly.
Here's my code:
login.java
public class login extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
Bundle bundle = getIntent().getExtras();
final boolean flag = false;
final String androidID = bundle.getString("androidID");
final Activity thisActivity = this;
final Context context = getApplicationContext();
// login using biometrics
Button btnBiometricLogin = findViewById(R.id.btnBiometricLogin);
btnBiometricLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkAndroidID async = new checkAndroidID(context);
async.getParentActivity(thisActivity);
async.setFlag(flag);
async.execute(androidID);
}
});
}
}
checkAndroidID.java
public class checkAndroidID extends AsyncTask <String, Void, String> {
openHTTP openHTTP = new openHTTP();
requestHTTP requests = new requestHTTP();
Activity parentActivity;
private WeakReference<Context> contextRef;
Boolean flag;
public checkAndroidID(Context context){
contextRef = new WeakReference<>(context);
}
public void getParentActivity(Activity parentActivity){
this.parentActivity = parentActivity;
}
public void setFlag (Boolean flag){
this.flag = flag;
}
#Override
protected String doInBackground(String... strings) {
try {
HttpURLConnection httpConn = openHTTP.prepareConnection("url");
String json = "{ \"androidID\": \"" + strings[0] + "\" }";
requests.sendData(json, httpConn);
return requests.receiveData(httpConn);
} catch (Exception e){
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String s) {
String[] result = s.split(";");
Context ctx = contextRef.get();
if (result[0].equals("TRUE")) flag = true;
if (!flag) Toast.makeText(parentActivity, "Biometric authentication is now unavailable." +
" Please login using username and password", Toast.LENGTH_SHORT).show();
else {
biometricUtils biometrics = new biometricUtils(ctx);
biometrics.getParentActivity(parentActivity);
biometrics.getUsername(result[1]);
biometrics.inovkeBiometricPrompt();
}
super.onPostExecute(s);
}
}
and biometricUtlis.java
public class biometricUtils {
Activity parentActivity;
String username;
Context context;
public void getParentActivity(Activity parentActivity){
this.parentActivity = parentActivity;
}
public void getUsername(String s){
this.username = s;
}
public biometricUtils(Context context){
this.context = context;
}
// creating a variable for our Executor
Executor executor = ContextCompat.getMainExecutor(context); // LINE 34
// this will give us result of AUTHENTICATION
final BiometricPrompt biometricPrompt = new BiometricPrompt((FragmentActivity) parentActivity, executor, new BiometricPrompt.AuthenticationCallback() {
#Override
public void onAuthenticationError(int errorCode, #NonNull CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
}
// THIS METHOD IS CALLED WHEN AUTHENTICATION IS SUCCESS
#Override
public void onAuthenticationSucceeded(#NonNull BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
Intent intent = new Intent(parentActivity.getApplicationContext(), tmp.class);
intent.putExtra("username", username);
parentActivity.startActivity(intent);
}
#Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
}
});
// creating a variable for our promptInfo
// BIOMETRIC DIALOG
final BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder().setTitle("Biometrical login")
.setDescription("Place your fingerprint on scanner to proceed").setNegativeButtonText("Cancel").build();
public void inovkeBiometricPrompt() {
biometricPrompt.authenticate(promptInfo);
}
}

How Best To Implement ViewModel( in AndroidX) So Data Survives Configuration Changes

I am trying to implement a ViewModel architecture for a RecyclerView in AndroidX, following the example as stated in enter link description here and enter link description here. Items in the recyclerView get selected on position clicked, but for some reason, the selected item de-select and revert to default after the device is rotated and configuration changed. I know there have been answers for questions like this in the past, but all I have seen are either not directly applicable in my case or are simply for deprecated cases.
CAN SOMEONE PLEASE TELL ME WHAT I AM DOING WRONG!
Below are snippets from my Code:
Dependencies added
dependencies {
def lifecycle_version = "2.2.0"
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
// Saved state module for ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
// Annotation processor
annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha02'
}
Repository Class:
public class TopicRepository {
private Application application;
private SharedPreferences sharedPreferences;
private ArrayList<RootTopic> topicGroupList;
private MutableLiveData<ArrayList<RootTopic>>topicGroupMLD;
public TopicRepository(Application application) {
this.application = application;
}
public LiveData<ArrayList<RootTopic>> getRootTopicLD(String subject){
if (topicGroupMLD == null){
topicGroupMLD = new MutableLiveData<ArrayList<RootTopic>>();
generateTopicGroup(subject);
}
return topicGroupMLD;
}
private void generateTopicGroup(final String subject){
Log.d(TAG, "generateTopicGroup: CALLED");
isRequestingMLD.postValue(true);
final String subjectTopicGroupList = subject + "TopicGroupList";
sharedPreferences = application.getSharedPreferences(AppConstant.Constants.PACKAGE_NAME, Context.MODE_PRIVATE);
String serializedTopicGroup = sharedPreferences.getString(subjectTopicGroupList, null);
if (serializedTopicGroup != null){
Gson gson = new Gson();
Type type = new TypeToken<ArrayList<RootTopic>>(){}.getType();
topicGroupList = gson.fromJson(serializedTopicGroup, type);
topicGroupMLD.postValue(topicGroupList);
}else {// - Not saved in SP
Log.d(TAG, "getTopicGroup: NOT IN SP");
new ActiveConnectionCheck(new ActiveConnectionCheck.Consumer() {
#Override
public void accept(Boolean internet) {
Log.d(TAG, "accept: CHECKED INTERNET");
if (internet){
Log.d(TAG, "accept: INTERNET CONNECTION = TRUE");
internetCheckMLD.postValue(AppConstant.Constants.IS_INTERNET_REQUEST_SUCCESS);
FirebaseFirestore fbFStore = FirebaseFirestore.getInstance();
CollectionReference lectureRef = fbFStore.collection(subject);
lectureRef.orderBy(AppConstant.Constants.POSITION, Query.Direction.ASCENDING)
.get().addOnSuccessListener(
new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
ArrayList<Topic>topicList = new ArrayList<>();
ArrayList<String> rootTitleList = new ArrayList<>();
for (QueryDocumentSnapshot snapshot : queryDocumentSnapshots){
Topic topic = snapshot.toObject(Topic.class);
topicList.add(topic);
}
Log.d(TAG, "onSuccess: TopicListSize = " + topicList.size());
for (Topic topic : topicList){
String rootTopicString = topic.getRootTopic();
if (!rootTitleList.contains(rootTopicString)){
rootTitleList.add(rootTopicString);
}
}
Log.d(TAG, "onSuccess: RootTitleListSize = " + rootTitleList.size());
for (int x = 0; x < rootTitleList.size(); x ++){
RootTopic rootTopic = new RootTopic(rootTitleList.get(x), new ArrayList<Topic>());
topicGroupList = new ArrayList<>();
topicGroupList.add(rootTopic);
}
for (int e = 0; e < topicList.size(); e++){
addTopicToGroup(topicGroupList, topicList.get(e));
}
topicGroupMLD.postValue(topicGroupList);
Gson gson = new Gson();
String serializedTopicGroup = gson.toJson(topicGroupList);
sharedPreferences.edit().putString(subjectTopicGroupList, serializedTopicGroup).apply();
Log.d(TAG, "onSuccess: TOPICGROUPSIZE = " + topicGroupList.size());
Log.d(TAG, "onSuccess: SERIALIZED GROUP = " + serializedTopicGroup);
isRequestingMLD.postValue(false);
}
}
).addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
isRequestingMLD.postValue(false);
Log.d(TAG, "onFailure: FAILED TO GET TOPICLIST e = " + e.toString());
}
}
);
}else {
internetCheckMLD.postValue(AppConstant.Constants.IS_INTERNET_REQUEST_FAIL);
Log.d(TAG, "accept: InternetCONECTION = " + false);
}
}
});
}
}
private void addTopicToGroup(ArrayList<RootTopic>rootGroup, Topic topic){
for (int x = 0; x < rootGroup.size(); x++){
RootTopic rootTopic = rootGroup.get(x);
if (rootTopic.getRootTopicName().equals(topic.getRootTopic())){
rootTopic.getTopicGroup().add(topic);
}
}
}
}
My ViewModel class
public class LectureViewModel extends AndroidViewModel {
public static final String TAG = AppConstant.Constants.GEN_TAG + ":LectureVM";
private Application application;
private TopicRepository topicRepository;
private ArrayList<RootTopic> topicGroupList;
public LectureViewModel(#NonNull Application application) {
super(application);
this.application = application;
topicRepository = new TopicRepository(application);
}
public LiveData<ArrayList<RootTopic>> getRootTopicListLD(String subject){
return topicRepository.getRootTopicLD(subject);
}
}
Activity Implementing ViewModel
public class LectureRoomActivity extends AppCompatActivity {
public static final String TAG = AppConstant.Constants.GEN_TAG + " LecRoom";
private LectureViewModel lectureRoomVM;
private String subject;
private RecyclerView mainRecyclerView;
private RootTopicAdapter rootTopicAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lecture_room);
Intent intent = getIntent();
subject = intent.getStringExtra(AppConstant.Constants.SUBJECT);
mainRecyclerView = findViewById(R.id.recyclerView);
downloadVM = new ViewModelProvider(this).get(DownloadLectureViewModel.class);
lectureRoomVM = new ViewModelProvider(this).get(LectureViewModel.class);
lectureRoomVM.getRootTopicListLD(subject).observe(
this,
new Observer<ArrayList<RootTopic>>() {
#Override
public void onChanged(ArrayList<RootTopic> rootTopics) {
if (rootTopics != null){
currentTopic = lectureRoomVM.getCursorTopic(subject, rootTopics);
setUpRec(rootTopics, currentTopic);
}
}
});
}
private void setUpRec( ArrayList<RootTopic>topicGroup, CursorTopic currentTopic){
rootTopicAdapter = new RootTopicAdapter(topicGroup,
new ArrayList<String>(), currentTopic.getParentPosition(),
currentTopic.getCursorPosition());
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(
this, RecyclerView.VERTICAL,false);
mainRecyclerView.setHasFixedSize(true);
mainRecyclerView.setLayoutManager(linearLayoutManager);
mainRecyclerView.setAdapter(rootTopicAdapter);
Log.d(TAG, "setUpRec: SETTING REC");
}
}
For saving and restoring UI related data you better use savedInstanceState Bundle to survive the last state. To achive this you simply override two methods in you UI activity. See the sample code snippet below.
In your RootTopicAdapter
// Add this where you detect the item click, probably in your adaptor class
private int lastRecyclerViewIndex; // define the variable to hold the last index
...
#Override
public void onClick(View v) {
lastRecyclerViewIndex = getLayoutPosition();
}
public int getLastIndex() {
return lastRecyclerViewIndex;
}
In your view model class
public class LectureViewModel extends AndroidViewModel {
public static final String TAG = AppConstant.Constants.GEN_TAG + ":LectureVM";
private Application application;
private TopicRepository topicRepository;
private ArrayList<RootTopic> topicGroupList;
public boolean mustRestore; // Is there any data to restore
public int lasIndexSelected;
public LectureViewModel(#NonNull Application application) {
super(application);
this.application = application;
topicRepository = new TopicRepository(application);
}
public LiveData<ArrayList<RootTopic>> getRootTopicListLD(String subject){
return topicRepository.getRootTopicLD(subject);
}
}
In you UI activity which uses the RecyclerView
public class LectureRoomActivity extends AppCompatActivity {
...
private LectureViewModel lectureRoomVM;
...
private RecyclerView mainRecyclerView;
private RootTopicAdapter rootTopicAdapter;
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lecture_room);
Intent intent = getIntent();
subject = intent.getStringExtra(AppConstant.Constants.SUBJECT);
mainRecyclerView = findViewById(R.id.recyclerView);
downloadVM = new ViewModelProvider(this).get(DownloadLectureViewModel.class);
lectureRoomVM = new ViewModelProvider(this).get(LectureViewModel.class);
lectureRoomVM.getRootTopicListLD(subject).observe(
this,
new Observer<ArrayList<RootTopic>>() {
#Override
public void onChanged(ArrayList<RootTopic> rootTopics) {
if (rootTopics != null){
currentTopic = lectureRoomVM.getCursorTopic(subject, rootTopics);
setUpRec(rootTopics, currentTopic);
// Exactly here, after setting up the data get your index for example
if(lectureRoomVM.mustRestore){
// Check the item count in the adaptor to avoid crashes
if(mainRecyclerView.getAdapter().getItemCount >= lastRecyclerViewIndex){
mainRecyclerView.findViewHolderForAdapterPosition(lastRecyclerViewIndex).itemView.performClick();
}
// After the restoration set the mustRestore to false
lectureRoomVM.mustRestore = false;
}
}
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.d(E, "onDestroy");
/*
* Here just set the mustRestore to true in order to be able to restore in onCreate method.
* If the application itself is not destroyed your data will still be live in the
* memory thanks to the ViewModel's life cycle awarness.
*/
lectureRoomVM.mustRestore = true;
}
}
There you go. Try this logic carefully without bugs. Then I think you will achive what you want to get.

Passing a variable between functions

I'm new to android studio and Java. My app uses jsoup to pass the contents of a website into an array where each element gets displayed on swipable flashcards (like tinder)
I've got a problem where my app crashes when I try to pass the result of the variable 'words' from onPostExecute() (line 123) to String num on line 49. I want to take the output of the function in onPostExcecute and set it as String num but I'm not sure how to do it.
public class AppHome extends AppCompatActivity implements PopupMenu.OnMenuItemClickListener {
TextView texx;
private ArrayList<String> al;
private ArrayAdapter<String> arrayAdapter;
private int i;
String words;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_app_home);
texx= findViewById(R.id.text1);
new doit().execute();
String num = words;
String str[] = num.split(",");
final ArrayList al = new ArrayList<String>(Arrays.asList(str));
arrayAdapter = new ArrayAdapter<>(this, R.layout.item, R.id.helloText, al );
SwipeFlingAdapterView flingContainer = (SwipeFlingAdapterView) findViewById(R.id.frame);
registerForContextMenu(flingContainer);
flingContainer.setAdapter(arrayAdapter);
flingContainer.setFlingListener(new SwipeFlingAdapterView.onFlingListener() {
#Override
public void removeFirstObjectInAdapter() {
// this is the simplest way to delete an object from the Adapter (/AdapterView)
Log.d("LIST", "removed object!");
al.remove(0);
arrayAdapter.notifyDataSetChanged();
}
#Override
public void onLeftCardExit(Object dataObject) {
//Do something on the left!
//You also have access to the original object.
//If you want to use it just cast it (String) dataObject
Toast.makeText(AppHome.this, "left", Toast.LENGTH_SHORT).show();
}
#Override
public void onRightCardExit(Object dataObject) {
Toast.makeText(AppHome.this, "right", Toast.LENGTH_SHORT).show();
}
#Override
public void onAdapterAboutToEmpty(int itemsInAdapter) {
// Ask for more data here
al.add("XML ".concat(String.valueOf(i)));
arrayAdapter.notifyDataSetChanged();
Log.d("LIST", "notified");
i++;
}
#Override
public void onScroll(float scrollProgressPercent) {
}
});
}
public class doit extends AsyncTask<Void,Void,Void> {
//String words;
#Override
protected Void doInBackground(Void... voids) {
try {
Document doc = Jsoup.connect("https://screenscrape4top40.000webhostapp.com/").get();
words=doc.text();
}catch(Exception e){e.printStackTrace();}
return null;
}
#Override
public void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
texx.setText(words);
//String str = (words);
//List<String> elephantList = Arrays.asList(str.split(","));
//texx.setText(elephantList.toString());
// texx.setText(elephantList);
}
}
}
public class doit extends AsyncTask<Void, Void, String> {
#Override
protected Void doInBackground(Void... voids) {
String words = "";
try {
Document doc = Jsoup.connect("https://screenscrape4top40.000webhostapp.com/").get();
words = doc.text();
} catch(Exception e) {
e.printStackTrace();
}
return words;
}
#Override
public void onPostExecute(String words) {
super.onPostExecute(aVoid);
texx.setText(words);
//String str = (words);
//List<String> elephantList = Arrays.asList(str.split(","));
//texx.setText(elephantList.toString());
// texx.setText(elephantList);
}
}
It should be fine now.
The problem is, you are not returning anything from the doInBackground method and hence you are not getting anything in the onPostExecute function.
You might consider checking the documentation for AsyncTask here.
In doInBackgroud() return the string(make sure it never beacome null) you want to use it on PostExecute()
also changed the data type of Parameter in onPostExecute method
onPostExecute(String Strs)
Then pass it to supper.OnPostExecute().
then u can use it.

Unable to call second activity from asynctask

I need to call a new activity from onPostExecute() method of ASyncTask but the context is returning null.
public class ImageDownloadTask extends AsyncTask<String,Void,ArrayList<String>> {
public final String search = "https://www.google.co.in/search?&tbm=isch&q=";
public final String searchAlbum = "album+art";
ArrayList<String> arrayList=new ArrayList<String>();
ArrayList<String> urlList=new ArrayList<String>();
Context context;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected ArrayList<String> doInBackground(String... urls) {
System.out.println(urls.length);
arrayList.clear();
urlList.clear();
for(int i=0;i<urls.length;i++) {
String url = urls[i];
String finalUrl = search + url + searchAlbum;
try {
//Log.i("URL", finalUrl);
urlList.add(finalUrl);
Document document = Jsoup.connect(finalUrl).get();
String result = document.toString();
//Pattern pattern = Pattern.compile("<img class=\"rg_ic rg_i\" data-src=\"(.*?)\" data-sz");
Pattern newPattern = Pattern.compile("\"ou\":\"(.*?)\",\"ow\"");
//Matcher m = pattern.matcher(result);
Matcher newMatcher = newPattern.matcher(result);
if(newMatcher.find())
arrayList.add(newMatcher.group(1));
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("Printing Images");
System.out.println(urlList);
System.out.println(arrayList);
return arrayList;
}
#Override
protected void onPostExecute(ArrayList<String> strings) {
if(context!=null) {
Intent i = new Intent(context,MusicPlayerActivity.class).putExtra("arrayImages",arrayList);
context.startActivity(i);}
else
Log.i("Context","NULL"); //Check why it is null*****
super.onPostExecute(strings);
}
}
The Output is Context:NULL.
Why is it null, i have tried making a variable of type MainActivity and Activity, but both doesn't solve the problem.
Thank you for your time.
You declare your context variable but never set it:
Context context;
So yes, it is null when you try and use it.
You should populate it before you try to use it - perhaps pass a reference to to the calling Activity or similar.
Put this ImageDownloadTask inside your Activity, then you can call it using below code
new MyTask().execute(urls);
and on you ImageDownloadTask change onPostExecute function to this one
#Override
protected void onPostExecute(ArrayList<String> strings) {
super.onPostExecute(strings);
Intent i = new Intent(YourActivityName.this, MusicPlayerActivity.class).putExtra("arrayImages", strings);
startActivity(i);
}
}
}

Why my Android PieChart drawing behaves abnormally and I get duplicated slices on screen rotation?

I need some help to fix this problem. I have a PieChart which is drawn in my android App using some data from a MySQL db. I am using an AsyncTask class implementation which loads the data from the server making an HTTPPostRequest and parsing the JSON response that is returned. The chart comes out fine and is drawn on the screen. The problem comes out when I rotate the device's screen: the Chart behaves abnormally and draws slices again... I don't know why it is doing that, but I read that if you rotate the screen all the methods of the Activity are called again (the onCreate(), onStart() and onResume() methods). Maybe it's because of that??? But I am not sure... Here is how is look like:
Then when I rotate the device:
The data are duplicated! Why? What am I mistaking?
Here is all the code:
public class ComeHaInvestito extends Activity {
/**** PieChartBuilder ****/
/** Colors to be used for the pie slices. */
private static int[] COLORS = new int[] { Color.GREEN, Color.BLUE, Color.MAGENTA, Color.CYAN };
/** The main series that will include all the data. */
private CategorySeries mSeries = new CategorySeries("");
/** The main renderer for the main dataset. */
private DefaultRenderer mRenderer = new DefaultRenderer();
/** Edit text field for entering the slice value. */
//private EditText mValue;
/** The chart view that displays the data. */
private GraphicalView mChartView;
private int HowmanyTimes;
#Override
protected void onRestoreInstanceState(Bundle savedState) {
super.onRestoreInstanceState(savedState);
mSeries = (CategorySeries) savedState.getSerializable("current_series");
mRenderer = (DefaultRenderer) savedState.getSerializable("current_renderer");
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable("current_series", mSeries);
outState.putSerializable("current_renderer", mRenderer);
}
/**** ComeHaInvestito ****/
// String which will store the values of the user
String municipalityName;
String year;
String versedMoney;
// List<Item> ArrayList that will be used to store data from DB
List<Item> MasterAndDetailstatisticsInfoList;
private static final String TAG_COMUNE = "mun_name";
private static final String TAG_ANNO = "year";
private static final String TAG_VERSED_MONEY = "versed_money";
private static final String TAG_SUCCESS = "success";
// POST request information
private static final String URL_ANDROID_APP_LISTENER = "http://xxx.xxx.xxx.xxx/androidApp/AndroidListener.php";
private ProgressDialog pDialog;
// JSONParser instance
JSONParser jParser = new JSONParser();
// JSON data retrieving information
private static final String JSON_STATISTICS_INFOS_LABEL = "statistics_infos";
private static final String JSON_MASTER_LABEL = "master";
private static final String JSON_DETAIL_LABEL = "detail";
private static final String JSON_MASTER_DETAIL_NAME_LABEL = "name";
private static final String JSON_MASTER_DETAIL_VALUE_LABEL ="value";
// statistics info JSON Array which will contain the Master and Detail data that will come from the POST request
JSONArray statisticsInfo = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_come_ha_investito);
Log.d("OnCREATE", "CREO L'ACTIVITY");
// recovering data from previous actitity
Intent iMieiDati = getIntent();
this.municipalityName = iMieiDati.getStringExtra(TAG_COMUNE);
this.year = iMieiDati.getStringExtra(TAG_ANNO);
this.versedMoney = iMieiDati.getStringExtra(TAG_VERSED_MONEY);
// instantiating the needed data structure
MasterAndDetailstatisticsInfoList = new ArrayList<Item>();
mRenderer.setStartAngle(270);
mRenderer.setDisplayValues(true);
new LoadAllMunicipalitiesInvestmentStatisticsThread().execute();
//mRenderer.setZoomButtonsVisible(true);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.pie_chart_builder2, menu);
return true;
}
#Override
protected void onResume() {
super.onResume();
if (mChartView == null) {
LinearLayout layout = (LinearLayout) findViewById(R.id.chart);
mChartView = ChartFactory.getPieChartView(this, mSeries, mRenderer);
mRenderer.setClickEnabled(true);
mChartView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SeriesSelection seriesSelection = mChartView.getCurrentSeriesAndPoint();
if (seriesSelection == null) {
Toast.makeText(ComeHaInvestito.this, "No chart element selected", Toast.LENGTH_SHORT).show();
}
else {
for (int i = 0; i < mSeries.getItemCount(); i++) {
mRenderer.getSeriesRendererAt(i).setHighlighted(i == seriesSelection.getPointIndex());
}
// mChartView.repaint();
Toast.makeText(
ComeHaInvestito.this,
"Chart data point index " + seriesSelection.getPointIndex() + " selected"
+ " point value=" + seriesSelection.getValue(), Toast.LENGTH_SHORT).show();
}
}
});
layout.addView(mChartView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
else {
//mChartView.repaint();
}
}
private void initChart() {
int i=0;
double value=0;
for (Item item : MasterAndDetailstatisticsInfoList) {
if (i == 4) {
break;
}
Log.d("Ciclo ", "NUMERO " + i);
if (item.getViewType() == EntryType.MASTER.ordinal()) {
MasterWithValue master = (MasterWithValue) item;
Log.d("MASTER NAME", master.getMasterName());
Log.d("MASTER VALUE", master.getMasterValue());
try {
value = Double.parseDouble(master.getMasterValue());
}
catch (NumberFormatException e) {
// value is not a decimal
}
mSeries.add(master.getMasterName(), value);
SimpleSeriesRenderer renderer = new SimpleSeriesRenderer();
renderer.setColor(COLORS[i%4]);
i++;
mRenderer.addSeriesRenderer(renderer);
Log.d("mSeries", mSeries.toString());
}
}
}
/**** Background Thread ****/
public class LoadAllMunicipalitiesInvestmentStatisticsThread extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(ComeHaInvestito.this);
pDialog.setMessage("Caricamento...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected String doInBackground(String... args) {
Log.d("ilMioComune", "Caricamento Statistiche Investimenti");
// building the HTTP POST request
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair(TAG_COMUNE, municipalityName));
params.add(new BasicNameValuePair(TAG_ANNO, year));
params.add(new BasicNameValuePair(TAG_VERSED_MONEY, versedMoney));
Log.d("params", params.toString());
JSONObject json = jParser.makeHttpRequest(URL_ANDROID_APP_LISTENER, "POST", params);
Log.d("JSON POST statistics investments", json.toString());
try {
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
statisticsInfo = json.getJSONArray(JSON_STATISTICS_INFOS_LABEL);
// foreach Statistics Master Entry
for (int i = 0; i<statisticsInfo.length(); i++) {
JSONObject JSONstatisticsInfo = statisticsInfo.getJSONObject(i);
JSONObject JSONmasterEntry = JSONstatisticsInfo.getJSONObject(JSON_MASTER_LABEL);
String masterEntryName = JSONmasterEntry.getString(JSON_MASTER_DETAIL_NAME_LABEL);
String masterEntryValue = JSONmasterEntry.getString(JSON_MASTER_DETAIL_VALUE_LABEL);
MasterAndDetailstatisticsInfoList.add(new MasterWithValue(masterEntryName, masterEntryValue));
JSONArray JSONdetails = JSONmasterEntry.getJSONArray(JSON_DETAIL_LABEL);
for (int j = 0; j<JSONdetails.length(); j++) {
JSONObject JSONdetailEntry = JSONdetails.getJSONObject(j);
String detailEntryName = JSONdetailEntry.getString(JSON_MASTER_DETAIL_NAME_LABEL);
String detailEntryValue = JSONdetailEntry.getString(JSON_MASTER_DETAIL_VALUE_LABEL);
MasterAndDetailstatisticsInfoList.add(new Detail(detailEntryName, detailEntryValue));
}
}
}
else {
// no statistics infos associated to the selected municipality were found
}
}
catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String file_url) {
pDialog.dismiss();
runOnUiThread(new Runnable() {
#Override
public void run() {
String MasterAndDetails = MasterAndDetailstatisticsInfoList.toString();
Log.d("List", MasterAndDetails);
// Creating the pie chart using the data recovered from the DB
initChart();
}
});
}
}
}
Does anyone have any idea on how to resolve this problem?
Thanks for the attention! Hope fore some help!
You are correct in that onCreate(), onResume(), etc. get called whenever you rotate. Because of this, you are calling new LoadAllMunicipalitiesInvestmentStatisticsThread().execute(); twice essentially.
You should move your data initialization logic to one place, and either load that data from the savedInstanceState, or call the initialize logic if the savedInstanceState returns null.
For example:
change declaration to
private CategorySeries mSeries = null;
in onCreate()
if(savedInstanceState != null)
mSeries = (CategorySeries) savedInstanceState.getSerializable("current_series");
if(mSeries == null)
{
mSeries = new CategorySeries("");
new LoadAllMunicipalitiesInvestmentStatisticsThread().execute(); //this line can be substituted for a new init method, which would contain the thread.execute
}

Categories