0

I need to set the String value generated by from AsynTask's OnPostExecute() method to Another Activity's Textview for that I have used following two methods, but both methods fails.

Method 1: By using GetterSetter Class

I am fairly new to android. I am making an app in which i stuck to this particular problem. I am running asyncTask from BackgroundTask class and BackgroundTask is running from StringGenerator class. In this AsyncTask I am setting value of a string to the getterSetter class.

My String Generator class -->

public class StringGenerator {
        ...
        new BackgroundTask(context).execute(sb.toString());
        Intent intent = new Intent(context.getApplicationContext(),Answer.class);
        context.startActivity(intent);
        sb.setLength(0);

}

My BackgroundTask Class -->

class BackgroundTask extends AsyncTask<String, Void, String> {

    Context context;

    GetterSetter getterSetter;

    ...   

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        Log.d("Answer",s);
        getterSetter = new GetterSetter();
        getterSetter.setString(s);
    }
}

My GetterSetter Class, here log prints correct string.So, the string is set here, I have verified it. -->

class GetterSetter{

    private String string;

    public String getString() {
        return string;
    }

    public void setString(String string) {
        this.string = string;
        Log.d("S1",string);
        Log.d("S2",this.string);
    }
}

From this getterSetter class i want to access string and set it onto textview onto another Activity called Answer Activity.

My Answer Activity -->

public class Answer extends AppCompatActivity {

    GetterSetter getterSetter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_answer);

        getterSetter = new GetterSetter();
        ((TextView)findViewById(R.id.SetSteps)).setText(getterSetter.getString());
    }
}

Problem with this method is -->

But the String value set on the textview is empty, so it prints nothing. Also, i tried to log the string.

Method 2 : By using SharedPreferences,but it always gives me default value which is ""(Empty).

My StringGenerator Class -->

public class StringGenerator {
            ...
            new BackgroundTask(context).execute(sb.toString());
            Intent intent = new Intent(context.getApplicationContext(),Answer.class);
            context.startActivity(intent);
            sb.setLength(0);

    }

My BackgroundTask Class -->

class BackgroundTask extends AsyncTask<String, Void, String> {

    Context context;
    SharedPreferences.Editor editor;

    BackgroundTask(Context context) {
        this.context = context;
        editor = context.getSharedPreferences("SolutionString",context.MODE_PRIVATE).edit();
    }

    ...

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        Log.d("Answer", s);
        editor.putString("Solution",s);
        editor.apply();
    }
}

My Answer Class -->

public class Answer extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_answer);

        SharedPreferences sharedPreferences = getSharedPreferences("SolutionString", MODE_PRIVATE);
        ((TextView)findViewById(R.id.SetSteps)).setText(sharedPreferences.getString("Solution",""));
    }
}

Problem with this method is -->

This method will set the correct output string only for first time, after that second time and onwards this method will print default value which is ""(Empty).I tries to debug this method via printing logs and in logs the string values are not empty, i got correct values in logs. So, I think in this method the problem is updation of sharedpreferences value. I have also researched about this on stackoverflow and tried following solution, but nothing works.

  1. SharedPreferences return only default value
  2. getPreferences always returns default value

and many more.

Can anyone tell me how can i access the string inside OnCreate Activity for first method?? or for second method I need to get the updated values for SharedPreferences.

I don't want to create another intent because, i am already running intent from String Generator class.

Avi Patel
  • 475
  • 6
  • 23
  • your background task is inside Answer class? –  May 19 '18 at 19:26
  • No, it's different class. – Avi Patel May 20 '18 at 12:18
  • where do you initialize the async class?plus why do you create an async task in a different class from that of the main? –  May 20 '18 at 12:24
  • I just called the constructor and execute doinbackground method, i dont need to initialize using object and i need to run both processes simultaneously because of performance issues, it takes long if i dont use AsyncTask. I will now try to use sharedpreferences to store and fetch values, i dont think this getter and setter will work. – Avi Patel May 20 '18 at 12:25
  • and where have you seen used it this way? –  May 20 '18 at 12:30
  • I have updated the question for using sharedpreferences to set "String"values for better understanding. – Avi Patel May 20 '18 at 12:56

2 Answers2

0

first of all new GetterSetter() will creates a new object... now lets see how the memory works...

class BackgroundTask extends AsyncTask<String, Void, String> {

    Context context;

    GetterSetter getterSetter;

    ...   

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        Log.d("Answer",s);
        getterSetter = new GetterSetter(); // assume is stored at address  2000 in the memory
        getterSetter.setString(s);
    }
}

public class Answer extends AppCompatActivity {

    GetterSetter getterSetter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_answer);

        getterSetter = new GetterSetter();// assume stored at 2008 in the memory , hence the string private String string does not have any value...
        ((TextView)findViewById(R.id.SetSteps)).setText(getterSetter.getString());
    }
}

Now here are the points :-

  1. private String string; if you declare this as private String string = ""; the null pointer exception will not occur.

  2. you should have single GetterSetter getterSetter; intialized getterSetter = new GetterSetter(); only once then the value will persist... if you have both the BackgroundTask and Answer in separate files Answer class wont be able to see BackgroundTask class GetterSetter...

  3. Rather include BackgroundTask with the Activity class and call the textview.setText in onPostExecute...

public class Answer extends AppCompatActivity {

GetterSetter getterSetter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_answer);

    getterSetter = new GetterSetter();

}

class BackgroundTask extends AsyncTask<String, Void, String> {

Context context;

...   

@Override
protected void onPostExecute(String s) {
    super.onPostExecute(s);
    Log.d("Answer",s);
    getterSetter.setString(s);

    ((TextView)findViewById(R.id.SetSteps)).setText(getterSetter.getString());
}

} }

  1. If you insist on using different files then BackgroundTask should be called first and

class BackgroundTask extends AsyncTask {

Context context;

public static GetterSetter getterSetter; // this will store the object in memory and the value will persist between classes...

...   

@Override
protected void onPostExecute(String s) {
    super.onPostExecute(s);
    Log.d("Answer",s);
    getterSetter = new GetterSetter();
    getterSetter.setString(s);
    // the activity Answer should start anywhere after this to get the correct value...
}

}

public class Answer extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_answer);

        ((TextView)findViewById(R.id.SetSteps)).setText(BackgroundTask.getterSetter.getString());
    }
}

Hope it helps...

Ahmad
  • 437
  • 1
  • 4
  • 12
  • I have applied second approach, but it didn't work, still prints empty string. Nullpointer exception is resolved though. – Avi Patel May 20 '18 at 05:50
  • I am passing intent from StringGenerator class after i execute AsyncTask. So, i want to run main thread for UI updation and AsyncTask to set the string values. – Avi Patel May 20 '18 at 06:00
  • I have updated the Answer, please check it out. And sorry i have tried your solution, but it didn't work. – Avi Patel May 20 '18 at 12:59
  • Startactivity should be in the onPostExecute... protected void onPostExecute(String s) { super.onPostExecute(s); Log.d("Answer",s); getterSetter = new GetterSetter(); getterSetter.setString(s); Intent intent = new Intent(context.getApplicationContext(),Answer.class); context.startActivity(intent); } – Ahmad May 24 '18 at 14:41
  • but it wont work as you have 2 new (allocated at different memory) declaration of GetterSetter... you can create a public static variable in StringGenerator of GetterSetter and then go through my answer ( 2 and 4 ) once again... – Ahmad May 24 '18 at 14:45
  • I have declared public static string and set it using setString method, but it started giving me nullpointerexception again, and yes i have assign string value = "", that you have suggested in GetterSetter class. – Avi Patel May 26 '18 at 15:36
  • See i am getting this error in my Answer.java class --> Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.io.sefu.rsolverfinalui.GetterAndSetter.getStr()' on a null object reference and my log value prints correct string. – Avi Patel May 26 '18 at 15:40
0

As you are creating a new object so the data in the existing object will be destroyed. So, the simplest way to do the above task is send the object with the intent. You can do this onPostExecute or on click of a button in your first Activity.

    Intent intent = new Intent(MainActivity.this, Answer.class);
    intent.putExtra("Object", getterSetter);
    startActivity(intent);

and your object i.e. GetterSetter must implements Serializable as:

    class GetterSetter implements Serializable

and in your another activity i.e. Answer.java you have to receive intent as:

    Intent rcv = getIntent();
    GetterSetter getterSetter = (GetterSetter) rcv.getSerializableExtra("Object");,

((TextView)findViewById(R.id.SetSteps)).setText(getterSetter.getString());
Raj
  • 2,997
  • 2
  • 12
  • 30
  • can i pass 2 intents?? 1 from StringGenerator and 1 from OnPostexecute method? I have performance issue, so i need to simultaneously run this both methods. – Avi Patel May 20 '18 at 05:51
  • You don't need to pass 2 intents. You can pass the object in this intent only. public class StringGenerator { ... new BackgroundTask(context).execute(sb.toString()); Intent intent = new Intent(context.getApplicationContext(),Answer.class); intent.putExtra("Object", getterSetter); context.startActivity(intent); sb.setLength(0); – Raj May 20 '18 at 06:29
  • why i need to implement serializable? – Avi Patel May 20 '18 at 06:47
  • 1
    By using Serializable you are converting the state of an object into a byte stream. And sending that in the intent. – Raj May 20 '18 at 06:50
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/171411/discussion-between-avi-patel-and-raj). – Avi Patel May 20 '18 at 06:51